如何合并具有相同数据值的相邻时间跨度?
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; }
}
}
我有一个包含逗号分隔值 (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; }
}
}