如何对一个集合进行分组并将相同的分组应用于其他相同长度的集合?

How to group one collection and apply same grouping to other, same-length collections?

我有多个相同长度的集合,一个 List<DateTime> 类型的时间戳集合和几个 List<double> 类型的数据集合。 List<double 中每个索引位置的值对应于 List<DateTime> 中的相应索引位置。

我希望能够通过应用于 List<DateTime>TimeSpan 压缩所有数据集合中的数据,并将时间戳分组到 TimeSpan 箱中并应用相同的分组到每个数据集合。

这是我目前"compress"时间戳的时间序列:

var someTimeStamps = new List<DateTime>(); 
                var compression = TimeSpan.FromHours(1).Ticks;
                var compressedTimeStamps = from rawData in someTimeStamps
                    group rawData by rawData.Ticks / numberTicks
                    into tickData
                    select new DateTime(tickData.Key * compression);

如何调整代码以使相同的分组也适用于数据集合 List<double>?我想应用对每个数据组内的值进行平均的分组逻辑。我的目标是提高计算效率,内存消耗不是我希望在这一点上优化的问题。

例如:

List<DateTime> 项:(为简单起见,以下值的顺序为(年、月、日、时、分、秒):

(1) 2018、8、14、08、20、05 (2) 2018、8、14、08、45、25 (3) 2018、8、14、09、02、53 (4) 2018、8、14、09、34、12 (5) 2018, 8, 14, 09, 44, 12

List<value> 项:

(1) 12 (2) 15 (3) 27 (4) 03 (5) 12

应用 TimeSpan.FromHours(1) 的压缩,两个集合的预期结果是:

List<DateTime> 项:

(1) 2018、8、14、08、00、00 (2) 2018, 8, 14, 09, 00, 00

List<double> 项(平均应用于每组中的项)

(1) 13.5(12 和 15 的平均值) (2) 14(平均 27、3 和 12)

您可以通过以下代码完成

List<DateTime> dateTimes = new List<DateTime>();
dateTimes.Add(new DateTime(2018, 8, 14, 08, 20, 05));
dateTimes.Add(new DateTime(2018, 8, 14, 08, 45, 25));
dateTimes.Add(new DateTime(2018, 8, 14, 09, 02, 53));
dateTimes.Add(new DateTime(2018, 8, 14, 09, 34, 12));
dateTimes.Add(new DateTime(2018, 8, 14, 09, 44, 12));

List<int> ints = new List<int>();
ints.Add(12);
ints.Add(15);
ints.Add(27);
ints.Add(03);
ints.Add(12);



var averages = dateTimes.Select((k, v) => new { k, v })
                        .GroupBy(x => new DateTime(x.k.Year, x.k.Month, x.k.Day, x.k.Hour, 0, 0))
                        .ToDictionary(g => g.Key, g => g.Select(x => ints.ElementAt(x.v)).Average());

输出:

编辑:

如果您希望将数据分成两个列表,例如 List<DateTime>List<double>,那么您可以将上述字典投射到键和值的分隔列表中。喜欢

 List<DateTime> dateTimeList = averages.Keys.ToList();
 List<double>  valuesList = averages.Values.ToList();

如果我没理解错的话

expand that problem to one time stamp series but multiple data series

var grouped = dateTimes
              .Zip(ints, (k, v) => new { k, v })
              .GroupBy(g => new DateTime(g.k.Year, g.k.Month, g.k.Day, g.k.Hour, 0, 0), g => g.v);

以上代码为您提供了日期时间和 wrt 多个数据系列的压缩

试试看对你有没有帮助。

我决定对每个数据点进行经典迭代,因为无论数据收集的数量有多少,它只需要一次迭代(感谢我的一位朋友建议分析这种方法):

public void CompressData(TimeSpan compression)
    {
        //declare generic buffer value function (bid/ask here)
        var bufferFunction = new Func<int, double>(index => (Bid[index] + Ask[index]) / 2);

        Open = new List<double>();
        High = new List<double>();
        Low = new List<double>();
        Close = new List<double>();
        var lastCompTs = -1L;
        var dataBuffer = new List<double>();
        var timeStamps = new List<DateTime>();

        for (int i = 0; i < TimeStamps.Count; ++i)
        {
            var compTs = TimeStamps[i].Ticks / compression.Ticks;
            if (compTs == lastCompTs)
            {
                //same timestamp -> add to buffer
                dataBuffer.Add(bufferFunction(i));
            }
            else
            {
                if (dataBuffer.Count > 0)
                {
                    timeStamps.Add(new DateTime(compTs * compression.Ticks));
                    Open.Add(dataBuffer.First());
                    High.Add(dataBuffer.Max());
                    Low.Add(dataBuffer.Min());
                    Close.Add(dataBuffer.Last());
                }

                lastCompTs = compTs;
                dataBuffer.Clear();
            }
        }

        if (dataBuffer.Count > 0)
        {
            timeStamps.Add(new DateTime(lastCompTs * compression.Ticks));
            Open.Add(dataBuffer.First());
            High.Add(dataBuffer.Max());
            Low.Add(dataBuffer.Min());
            Close.Add(dataBuffer.Last());
        }

        //assign time series collection
        TimeStamps = timeStamps;
    }