重组对象

时间:2012-03-27 17:26:54

标签: c# linq

我想拍一个这样的物体:

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

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

SortedList<DateTime, SortedList<string, double>>

或者,更好的是,这个:

SortedList<DateTime, double[]>

其中每个'double []'包含的元素与SortedList中的KeyValue对一样多。

我猜Linq是要走的路,但无法弄清楚。感谢您的任何建议。

5 个答案:

答案 0 :(得分:1)

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));

答案 1 :(得分:0)

第二种情况非常简洁:

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;
    }
}

答案 2 :(得分:0)

  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())
  );

答案 3 :(得分:0)

如果使用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);

答案 4 :(得分:0)

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);