重组对象

本文关键字:对象 重组 | 更新日期: 2023-09-27 18:29:06

我想要一个这样的对象:

SortedList<string, SortedList<int, SortedList<DateTime, double>>> Data

并且,对于给定的"int"值(第一个嵌套排序列表的键),将其重组为:

SortedList<DateTime, SortedList<string, double>>

或者,更好的是,这个:

SortedList<DateTime, double[]>

其中,每个"double[]"的元素数量与SortedList中的KeyValue对的数量相同。

我猜林克是个不错的选择,但我想不通。谢谢你的建议。

重组对象

digEmAll击败了我,但这里是查询理解语法中的第二种情况:

int desiredInt = //whatever...
var query = from pair in Data
        from pair2 in pair.Value
        where pair2.Key == desiredInt
        from pair3 in pair2.Value
        group pair3.Value by pair3.Key into grp
        select new { grp.Key, Value = grp.ToArray() };
var result = new SortedList<DateTime, double[]>(query.ToDictionary(a => a.Key, a => a.Value));
  int givenKey = ...;
  var variant1 = new SortedList<DateTime, SortedList<string, double>>(
    Data.Select(pair => new { str = pair.Key, dateValues = pair.Value[givenKey] })
    .Where(pair => pair.dateValues != null)
    .SelectMany(pair => pair.dateValues.Select(dateValue => new { pair.str, date = dateValue.Key, value = dateValue.Value }))
    .GroupBy(pair => pair.date)
    .ToDictionary(group => group.Key, group => new SortedList<string, double>(group.ToDictionary(triple => triple.str, triple => triple.value)))
  );
  var variant2 = new SortedList<DateTime, double[]>(
    Data.Select(pair => new { str = pair.Key, dateValues = pair.Value[givenKey] })
    .Where(pair => pair.dateValues != null)
    .SelectMany(pair => pair.dateValues.Select(dateValue => new { pair.str, date = dateValue.Key, value = dateValue.Value }))
    .GroupBy(pair => pair.date)
    .ToDictionary(group => group.Key, group => group.Select(triple => triple.value).ToArray())
  );

如果您使用DateTime的全分辨率,则您的转换是不可能的,除非您的系统以某种方式正则化插入的DateTime值。即使是非常快速的插入也可能发生在不同的刻度上。如果你将其正则化,那么你可以得到如下值:

Dictionary<DateTime, double[]> results = (from d1 in Data
                                          from d2 in d1.Value
                                          where d2.Key == 1
                                          from d3 in d2.Value
                                          group d3 by d3.Key into d3Group
                                          select new {Key = d3Group.Key, Value = (from d4 in d3Group
                                                                                  select d4.Value).ToArray()
                                                      }).ToDictionary(element => element.Key, element => element.Value);
SortedList<DateTime, double[]> newSortedList = new SortedList<DateTime, double[]>(results);

第二种情况非常简洁:

var dateGroups = Data.SelectMany(x => x.Value)
                     .SelectMany(x => x.Value)
                     .GroupBy(x => x.Key)
                     .ToSortedList(g => g.Key, 
                                   g => g.Select(x => x.Value).ToArray());

相反,第一个案例似乎是错误的,我怀疑它应该是:

SortedList<DateTime, SortedList<string, double[]>>

如果是这样的话,代码如下:

var dict = 
(from x in Data
 from y in x.Value
 from z in y.Value
 select new { StrKey = x.Key, IntKey = y.Key, DateKey = z.Key, Value = z.Value })
.GroupBy(x => x.DateKey)
.ToSortedList(g1 => g1.Key,
              g1 => g1.GroupBy(x => x.StrKey)
                      .ToSortedList(g2 => g2.Key,
                                    g2 => g2.Select(y => y.Value).ToArray()));

其中ToSortedList是以下扩展:

public static class Exts
{
    public static SortedList<TK, TV> ToSortedList<TEl, TK, TV>(
        this IEnumerable<TEl> elements,
        Func<TEl, TK> keySelector, 
        Func<TEl, TV> valueSelector)
    {
        if(elements == null || keySelector == null || valueSelector == null)
            throw new ArgumentNullException("An argument of ToSortedList is null");
        var dict = new SortedList<TK, TV>();
        foreach (var el in elements)
            dict.Add(keySelector(el), valueSelector(el));
        return dict;
    }
}

Phoog的答案很好,但也许你应该考虑ILookup而不是SortedList。。。

ILookup<DateTime, double> result =
(
  from pair1 in Data
  from pair2 in pair1.Value
  where pair2.Key == givenInt
  from pair3 in pair2.Value
  from theDouble in pair3.Value
  select new {theDateTime = pair3.Key, theDouble = theDouble }
)
.ToLookup(x => x.theDateTime, x => x.theDouble);