扩展我的linq查询时遇到一些困难。
假设我有以下数据:
Vault Items
----- -----
1 100, 102
2 100, 102
3 101
4 101
我想扁平化这个数组,所以我明白了:
Items Vaults
----- ------
100, 102 1, 2
101 3, 4
我目前拥有的代码就是这个
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
var Vaults = new[]
{
new Vault
{
Id = 1,
Contents = new Contents
{
Items = new[]
{
new Item
{
Id = 100,
Number = "100"
},
new Item
{
Id = 102,
Number = "102"
}
}
}
},
new Vault
{
Id = 2,
Contents = new Contents
{
Items = new[]
{
new Item
{
Id = 100,
Number = "100"
},
new Item
{
Id = 102,
Number = "102"
}
}
}
},
new Vault
{
Id = 3,
Contents = new Contents
{
Items = new[]
{
new Item
{
Id = 101,
Number = "101"
}
}
}
},
new Vault
{
Id = 4,
Contents = new Contents
{
Items = new[]
{
new Item
{
Id = 101,
Number = "101"
}
}
}
}
};
var grouping = Vaults.SelectMany(
c => c.Contents.Items.Select(s => new { Item = s, Vault = c }))
.GroupBy(o => o.Item.Id)
.Select(
grouping1 =>
new Tuple<Item, IEnumerable<Vault>>(
grouping1.First().Item, grouping1.Select(o => o.Vault)));
foreach (var tuple in grouping)
{
Console.WriteLine("Item(s) {0}: Vault {1}", tuple.Item1.Number,
String.Join(", ", tuple.Item2.Select(c => c.Id.ToString()).ToArray()));
}
}
}
public class Vault
{
public long Id { get; set; }
public Contents Contents { get; set; }
}
public class Contents
{
public IEnumerable<Item> Items { get; set; }
}
public class Item
{
public long Id { get; set; }
public string Number { get; set; }
}
此查询尚未完成,因为它没有在项目列表上进行分组,结果与此类似:
Item Vaults //Note: this isn't the output I need
---- ------
100 1, 2
102 1, 2
101 3, 4
有人能指出我正确的方向来修复此查询吗? 对于此示例,我们可以假设保管库共享的项目始终相同。 (含义Vault 2 必须包含与Vault 1完全相同的项目)
答案 0 :(得分:2)
你可以这样做:
首先,将GetHashCode
和Equals
添加到Item
,如下所示:
public class Item {
public long Id { get; set; }
public string Number { get; set; }
public override bool Equals(object obj) {
if (obj == this) return true;
var other = obj as Item;
if (other == null) return false;
return Id == other.Id;
}
public override int GetHashCode() {
return Id.GetHashCode();
}
}
接下来,定义一个可以比较项集的相等性的类,如下所示:
internal class MultipartKey<T> {
private readonly HashSet<T> items;
private readonly int hashCode;
public MultipartKey(IEnumerable<T> items) {
this.items = new HashSet<T>(items);
hashCode = this.items.Where(i => i != null)
.Aggregate(0, (p, v) => p*31 + v.GetHashCode());
}
public override int GetHashCode() {
return hashCode;
}
public override bool Equals(object obj) {
if (obj == this) return true;
var other = obj as MultipartKey<T>;
if (other == null) return false;
return items.SetEquals(other.items);
}
}
现在您的查询可以表达如下:
var grouping = Vaults
.GroupBy(v => new MultipartKey<Item>(v.Contents.Items))
.Select(g => new {
Items = g.First().Contents.Items
, Vaults = g.ToList()
});
foreach (var g in grouping) {
Console.WriteLine("{0} ---- {1}"
, string.Join(",", g.Items.Select(i=>i.Id))
, string.Join(",", g.Vaults.Select(v => v.Id))
);
}