Linq Transpose List

时间:2015-02-06 05:08:39

标签: c# linq

我有简单对象列表:

 var r = new  List
        {
            new { Id = 1, Value = 2, DateTime = DateTime.Parse("10.10.2014")},
            new { Id = 2, Value = 3, DateTime = DateTime.Parse("10.10.2014")},
            new { Id = 3, Value = 4, DateTime = DateTime.Parse("10.10.2014")},
            new { Id = 1, Value = 5, DateTime = DateTime.Parse("11.10.2014")},
            new { Id = 2, Value = 6, DateTime = DateTime.Parse("11.10.2014")}
        };

我希望得到像这样的对象:

DateTime    | 1 | 2 | 3 |
10.10.2014  | 2 | 3 | 4 |
11.10.2014  | 5 | 6 |   |

对此有什么好的linq查询吗?像sql中的pivot / unpiv一样的Smth可能吗?

3 个答案:

答案 0 :(得分:1)

试试这个:

r.ToLookup(t => t.id, t=>t.DateTime)

如果这不起作用,请通读this

您希望根据ID对列表进行分组,然后按字典键入结果列表。您应该可以使用GroupBy的某种组合来创建分组列表和ToDictionary()的组合,这些组合允许您将对象的属性指定为键并从中创建字典。

答案 1 :(得分:0)

您正在寻找一个简单的GroupBy

var result = r.GroupBy(x => x.DateTime)
              .Select (grp => new
               {
                   DateTime = grp.Key,
                   _1 = grp.Where(x => x.Id == 1).Select(x => x.Value).Cast<Int32?>().FirstOrDefault(),
                   _2 = grp.Where(x => x.Id == 2).Select(x => x.Value).Cast<Int32?>().FirstOrDefault(),
                   _3 = grp.Where(x => x.Id == 3).Select(x => x.Value).Cast<Int32?>().FirstOrDefault()
               });

result现在是:

enter image description here

答案 2 :(得分:0)

如果在编译时未知Ids的数量,则无法创建链接语句以将这些ID捕获为新字段。 Linq就可以做到这一点。在这种情况下你能做的最好的是:

var ids = r.Select(x => x.Id).Distinct().OrderBy(x => x).ToArray();

var query =
    from x in r
    group x by x.DateTime into gxs
    let lookup = gxs.ToLookup(x => x.Id, x => (int?)x.Value)
    select new
    {
        DateTime = gxs.Key,
        Values = ids.Select(i => new
        {
            Id = i,
            Value = lookup[i].FirstOrDefault(),
        }).ToArray(),
    };

这产生了这个:

result

如果知道了ID,那么以下变化是最好的:

var query =
    from x in r
    group x by x.DateTime into gxs
    let lookup = gxs.ToLookup(x => x.Id, x => (int?)x.Value)
    select new
    {
        DateTime = gxs.Key,
        _1 = lookup[1].FirstOrDefault(),
        _2 = lookup[2].FirstOrDefault(),
        _3 = lookup[3].FirstOrDefault(),
    };