如何合并具有相同数据值的相邻时间跨度?

How do I merge adjacent time spans with the same data value?

我有一个包含逗号分隔值 (CSV) 的文件,格式如下:

26/09/2015,GROUP_1,0,0,0,0,0,0,0,0,0,0,12345.006,12345.006,27469.005,27469.005,27983.005,27983.005,28081.005,0,0,0,28105.005,28105.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

每个数字代表 15 分钟间隔内的工作时间,范围在 8:00 上午 - 8:00 下午。首次开始时间为08:00:00),最后一次开始时间为19:45:00;有 49 "columns" 条数据。

0,0,0,0,0,0,0,0,0,0,12345.006,12345.006,27469.005,27469.005,27983.005,27983.005,28081.005,0,0,0,28105.005,28105.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

日期将是 "event" 发生的日期,也是数据上的日期。但我需要获取相同的值并指定一个时间范围。例如,前两个非零值相同:

12345.006,12345.006 

这些从 10:30 和 10:45 开始;我需要合并这些并报告 12345 小时的时间跨度 10:30 - 11:00 am.

我阅读了文件;我将这些值作为一个数组,我遇到的问题是如何将相同的值 "group" 放入适当的时间范围。

DateTime startDate = new DateTime(2015,08,05);
DateTime finisDahte = new DateTime(2015,08,05);
int column = 0;
for (int i = 0; i < data.Length; i++)
{
    //timerange start with every 15 minutes by column
    if (column >= 2)
    {
        if (data[i] != "0")
        {
            //Getting rid of decimals, they are not neccesary and that's how the file have it, I dont know why
            if (data[i].Contains('.'))
            {
                data[i] = data[i].Substring(0, data[i].LastIndexOf('.'));

            }

            //we check if there is a next index to compare the same value
            if ((i + 1) <= totalElementos)
            {

                var nextElem = data[i + 1];
                if (nextElem != "0")
                {
                    nextElem.Substring(0, nextElem.LastIndexOf('.'));
                }
                else
                {
                    //the is no next element... something here
                }

                //CRUCIAL PART: if the current index it's the same as the next one, it means they share the time range
                if (data[i] == nextElem)
                {
                    //the same index as the next one
                    //I need to identify when it's the first time I'm comparing a value with the next one, so I can set a start date
                    //I need to sum the total amount of time ranges for every repetition they have and save when the value start and when the value is different (so it's a new value)
                }
                else
                {
                    //it's not the same index, so technically the finishdate will be set here?
                }
            }
            else
            {
                //there is not more indexes, so finishdate will be here
            }

        }

    }

    //column++;
}

希望我能解释一下。谢谢

这不是编码服务;你需要走得更远一点。您已经很好地概述了您的算法;现在,您应该输入一些打印语句来跟踪代码的运行。循环和 if 语句是否为您提供了您期望的控制流?这样做的一个好方法是将您的评论放入打印语句中,例如在您最后的内部评论中:

print "there is not more indexes, so finishdate will be here"

同时打印循环索引、找到的值等。

一旦你纠正了那里的任何流程问题,就开始用有用的代码填充注释块,一次几行或一个块。

当您遇到特定问题时,post 您的代码和实际输出。这就是 Whosebug 旨在帮助您的地方。


与此同时,我想更改一下您的外循环。让它作为一个 while 循环被驱动,这样你就可以根据需要自由地推进你的索引。现在,您出于几乎相同的目的保留了两个变量:i 和 column。相反,只使用一个,例如:

column = 0
while (column < data.Length)
    // Find all of the indices with the same consecutive value
    finish_index = column;
    while data[start_column] = data[finish_index+1]
        finish_index++;
    // You now have the range of work slots to merge.
    printf "Time slots %d - %d have %d work hours", column, finish_index, int(data[column])

    column = finish_index+1
}

您仍然需要将列数转换为时间:15 分钟 * 列 + 8:00am。我还遗漏了一些中间的好步骤,但我认为您已经在评论中有了它们。

这让你感动吗?

您需要像下面的代码一样生成一个 class。我将日期更改为美国格式以进行测试。下面的代码使用 StringReader 从字符串读取,而当从文件读取时使用 StreamReader。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<DataSample> samples = new List<DataSample>();
            string data = "9/26/2015,GROUP_1,0,0,0,0,0,0,0,0,0,0,12345.006,12345.006,27469.005,27469.005,27983.005,27983.005,28081.005," +
                          "0,0,0,28105.005,28105.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n";
            StringReader reader = new StringReader(data);
            string inputline = "";

            while ((inputline = reader.ReadLine()) != null)
            {

                string[] dataArray = inputline.Split(new char[] { ',' });
                DateTime startDate = DateTime.Parse(dataArray[0]);
                startDate = startDate.AddHours(8);

                DateTime timeCounter = startDate;
                string groupName = dataArray[1];

                for (int i = 2; i < dataArray.Length; i++)
                {
                    if (dataArray[i] != "0")
                    {
                        DataSample newSample = new DataSample();
                        samples.Add(newSample);
                        newSample.name = groupName;
                        newSample.time = timeCounter;
                        newSample.value = double.Parse(dataArray[i]);
                    }
                    timeCounter = timeCounter.AddMinutes(15);
                }
            }

            var groupByValue = samples.AsEnumerable()
                .GroupBy(x => x.value)
                .ToList();

            foreach (var group in groupByValue)
            {
                Console.WriteLine("Value : {0}, Times : {1}", group.Key.ToString(), string.Join(",",group.Select(x => x.time.ToString())));
            }
            Console.ReadLine();
        }

    }
    public class DataSample
    {
        public string name { get; set; }
        public DateTime time { get; set; }
        public double value { get; set; }
    }

}
​