示例类:
public class Pallet
{
public int Id { get; set; }
public List<Location> Locations { get; set; }
}
public class Location
{
public int Id { get; set; }
}
鉴于此输入:
var input = new List<Pallet>
{
new Pallet
{
Id = 1,
Locations = new List<Location>
{
new Location { Id = 1 },
new Location { Id = 3 }
}
},
new Pallet
{
Id = 2,
Locations = new List<Location>
{
new Location { Id = 2 }
}
},
new Pallet
{
Id = 1,
Locations = new List<Location>
{
new Location { Id = 1 },
new Location { Id = 4 }
}
},
};
是否有一种很好的LINQ方法可以将重复项(在父集合和子集合中)折叠到相当于此的位置?
var output = new List<Pallet>
{
new Pallet
{
Id = 1,
Locations = new List<Location>
{
new Location { Id = 1 },
new Location { Id = 3 },
new Location { Id = 4 }
}
},
new Pallet
{
Id = 2,
Locations = new List<Location>
{
new Location { Id = 2 }
}
}
};
是的,我可以迭代收集并手动合并项目,但我很好奇LINQ会/可以提供更具表现力的东西。
答案 0 :(得分:3)
您可以使用GroupBy
收集匹配的ID,然后使用Select
创建新的收藏集:
var output = input.GroupBy(pallet => pallet.Id)
.Select(grp => new Pallet {
Id = grp.Key,
Locations = grp.SelectMany(pallet => pallet.Locations).Distinct().ToList()
}).ToList();
上面提到的一点是,Distinct()
只能在课程类型上正常工作,如果你要么提供IEqualityComparer<Location>
,要么拥有&#34;位置&#34;类实现IEquatable<Location>
(并覆盖object.GetHashCode
):
public class Location : IEquatable<Location>
{
public int Id { get; set; }
public bool Equals(Location other)
{
//Check whether the compared object is null.
if (object.ReferenceEquals(other, null)) return false;
//Check whether the compared object references the same data.
if (object.ReferenceEquals(this, other)) return true;
return Id == other.Id;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
或者,您可以在选择每个组中的第一个位置时使用第二个GroupBy
代替所有爵士乐:
var output = input.GroupBy(pallet => pallet.Id)
.Select(grp => new Pallet {
Id = grp.Key,
Locations = grp.SelectMany(pallet => pallet.Locations)
.GroupBy(location => location.Id)
.Select(location => location.First())
.ToList()
}).ToList();
答案 1 :(得分:2)
这个足够好吗?
var output = from p in input
group p by p.Id into g
select new Pallet
{
Id = g.Key,
Locations = (from l in g.SelectMany(x => x.Locations)
group l by l.Id into gl
select new Location { Id = gl.Key }).ToList()
};