C# LINQ合并两个列表(复合键上的完全外部联接)
我有两张单子C# LINQ合并两个列表(复合键上的完全外部联接),c#,linq,C#,Linq,我有两张单子 IEnumerable<Citrus> grapefruit = citrusList.Where(x => x.IsSmall == false); IEnumerable<Citrus> tangerines = citrusList.Where(x => x.IsSmall == true); 但我相信有更好的办法。我想基本上做一个完整的外部连接(把所有的葡萄柚和橘子结合起来,但把橘子从交叉处弄出来)。我的最终目标是有一个包装容器,里
IEnumerable<Citrus> grapefruit = citrusList.Where(x => x.IsSmall == false);
IEnumerable<Citrus> tangerines = citrusList.Where(x => x.IsSmall == true);
但我相信有更好的办法。我想基本上做一个完整的外部连接(把所有的葡萄柚和橘子结合起来,但把橘子从交叉处弄出来)。我的最终目标是有一个包装容器,里面有一些葡萄柚,一些橘子和一些橘子。我相信在LINQ中有一种更优雅的方式可以做到这一点
…但我无法从和中找出它,它不完全是一个联盟,因为我正在修改交叉成员(http://msdn.microsoft.com/en-us/library/bb341731.aspx)
帮个小忙 实际上,听起来你需要一个内部连接,而不是外部连接。嵌套for循环实际上执行的是内部联接的等效操作。无论如何:
grapefruit
.Join(
tangerines,
x => new { Color = x.Color, Flavor = x.Flavor, Texture = x.Texture, State = x.State },
x => new { Color = x.Color, Flavor = x.Flavor, Texture = x.Texture, State = x.State },
(o,i) => new Tangelo(o.Color, o.Flavor, o.Texture, o.State, "A tangelo", new Decimal(0.75))
).Map(x => container.Add(x));
其中,“Map”是IEnumerables的“ForEach”式扩展方法:
public static void Map<T>(this IEnumerable<T> source, Action<T> func)
{
foreach (T i in source)
func(i);
}
然后,您可以使用David B答案中的map方法或AddRange方法将它们添加到容器中。您不需要完全的外部连接,否则您将制作一些不含葡萄柚的桔子和一些不含桔子的桔子 这是一个内部连接
List<Tangelo> tangelos = (
from fruit in grapefruit
join fruitToo in tangerines
on new {fruit.Flavor, fruit.Color, fruit.Flavor, fruit.State}
equals new {fruitToo.Flavor, fruitToo.Color, fruitToo.Flavor, fruitToo.State}
select new Tangelo(fruit.Color, fruit.Flavor, fruit.Texture, fruit.State,
"A tangelo", new Decimal(0.75))
).ToList()
我认为这样做很有效:
var cs = from c in citrusList
group c by new { c.Color, c.Flavor, c.Texture, c.State } into gcs
let gs = gcs.Where(gc => gc.IsSmall == false)
let ts = gcs.Where(gc => gc.IsSmall == true)
let Tangelos = gs
.Zip(ts, (g, t) =>
new Tangelo(g.Color, g.Flavor, g.Texture, g.State,
"A tangelo", new Decimal(0.75)))
select new
{
gcs.Key,
Grapefruit = gs.Skip(Tangelos.Count()),
Tangerines = ts.Skip(Tangelos.Count()),
Tangelos,
};
var container = new PackingContainer();
container.AddRange(from c in cs
from f in c.Grapefruit
.Concat(c.Tangerines)
.Concat(c.Tangelos.Cast<Citrus>())
select f);
var cs=来自citrusList中的c
c组通过新的{c.颜色,c.风味,c.质地,c.状态}进入gcs
设gs=gcs.Where(gc=>gc.IsSmall==false)
设ts=gcs.Where(gc=>gc.IsSmall==true)
设Tangelos=gs
.Zip(ts,(g,t)=>
新探戈乐(g.颜色、g.风味、g.质地、g.状态、,
“探戈舞曲”,新十进制(0.75)
选择新的
{
地面军事系统键,
葡萄柚=gs.Skip(Tangelos.Count()),
Tangerines=ts.Skip(Tangelos.Count()),
坦格洛斯,
};
var container=新的打包容器();
container.AddRange(从c到cs
从f到c.葡萄柚
香菇
.Concat(c.Tangelos.Cast())
选择f);
内部联接只返回可制成桔子的葡萄柚和橘子。()我要所有的葡萄柚和橘子,但我要所有符合规定标准的葡萄柚和橘子都变成橘子。在我看来,这似乎是一个完整的外部连接()似乎是一个不错的答案,尽管在这种复杂程度上,我认为我最好还是坚持使用foreach循环。看起来这对LINQ来说并不是一个简单的例子。我想要葡萄柚不带橘子,橘子不带橘子,但橘子不带一些葡萄柚和橘子的交叉点。关于1:M匹配的观点很好,我想要葡萄柚和橘子之间的1:1映射,它们被制成橘子?可能但是很乱。这并不是我想要的“在LINQ中做这件事更优雅的方式”。Zip看起来像一个扩展函数,有多个let和where…我很想看看与基本嵌套foreach循环的性能比较。
List<Tangelo> tangelos = (
from fruit in grapefruit
join fruitToo in tangerines
on new {fruit.Flavor, fruit.Color, fruit.Flavor, fruit.State}
equals new {fruitToo.Flavor, fruitToo.Color, fruitToo.Flavor, fruitToo.State}
select new Tangelo(fruit.Color, fruit.Flavor, fruit.Texture, fruit.State,
"A tangelo", new Decimal(0.75))
).ToList()
List<Tangelo> tangelos = (
from fruit in tangerines
where grapefruit.Any(fruitToo =>
new {fruit.Flavor, fruit.Color, fruit.Flavor, fruit.State}
== new {fruitToo.Flavor, fruitToo.Color, fruitToo.Flavor, fruitToo.State})
select new Tangelo(fruit.Color, fruit.Flavor, fruit.Texture, fruit.State,
"A tangelo", new Decimal(0.75))
).ToList()
container.AddRange(tangelos);
var cs = from c in citrusList
group c by new { c.Color, c.Flavor, c.Texture, c.State } into gcs
let gs = gcs.Where(gc => gc.IsSmall == false)
let ts = gcs.Where(gc => gc.IsSmall == true)
let Tangelos = gs
.Zip(ts, (g, t) =>
new Tangelo(g.Color, g.Flavor, g.Texture, g.State,
"A tangelo", new Decimal(0.75)))
select new
{
gcs.Key,
Grapefruit = gs.Skip(Tangelos.Count()),
Tangerines = ts.Skip(Tangelos.Count()),
Tangelos,
};
var container = new PackingContainer();
container.AddRange(from c in cs
from f in c.Grapefruit
.Concat(c.Tangerines)
.Concat(c.Tangelos.Cast<Citrus>())
select f);