Linq 转置列表
Linq Transpose List
我有简单对象列表:
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/unpivot?
试试这个:
r.ToLookup(t => t.id, t=>t.DateTime)
如果这不起作用,请通读 this
您希望根据 id 对列表进行分组,然后通过字典对结果列表进行键控。您应该能够使用 GroupBy 和 ToDictionary() 的某种组合来做到这一点,它创建一个分组列表的列表和 ToDictionary(),它创建允许您将对象的 属性 指定为键并从中创建一个字典。
您正在寻找一个简单的 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
现在是:
如果在编译时不知道 ID 的数量,则无法创建 link 语句来将这些 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(),
};
产生这个:
如果 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(),
};
我有简单对象列表:
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/unpivot?
试试这个:
r.ToLookup(t => t.id, t=>t.DateTime)
如果这不起作用,请通读 this
您希望根据 id 对列表进行分组,然后通过字典对结果列表进行键控。您应该能够使用 GroupBy 和 ToDictionary() 的某种组合来做到这一点,它创建一个分组列表的列表和 ToDictionary(),它创建允许您将对象的 属性 指定为键并从中创建一个字典。
您正在寻找一个简单的 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
现在是:
如果在编译时不知道 ID 的数量,则无法创建 link 语句来将这些 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(),
};
产生这个:
如果 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(),
};