前言:我不明白这是做什么的:
o => o.ID, i => i.ID, (o, id) => o
所以对我很轻松。 : - )
我有两个需要加入的列表:
// list1 contains ALL contacts for a customer.
// Each item has a unique ID.
// There are no duplicates.
ContactCollection list1 = myCustomer.GetContacts();
// list2 contains the customer contacts (in list1) relevant to a REPORT
// the items in this list may have properties that differ from those in list1.
/*****/// e.g.:
/*****/ bool SelectedForNotification;
/*****/// may be different.
ContactCollection list2 = myReport.GetContacts();
我需要创建第三个ContactCollection,其中包含list1
中的所有联系人,但是如果项目在列表中,则包含list2
中项目的属性[2]({{1 }})。
我需要将list3.Count == list1.Count
中的所有项目替换为list1
中list2
项中的项目list1
中的项目ID。结果列表(list2
)应在list3
包含相同数量的项目。
我觉得我没有任何意义。所以,请在评论中提问,我会尽力澄清。
答案 0 :(得分:52)
加入并不是那么困难,但你的问题可能会使用一些进一步的解释。
要加入两个列表,您可以执行类似
的操作var joined = from Item1 in list1
join Item2 in list2
on Item1.Id equals Item2.Id // join on some property
select new { Item1, Item2 };
这将给出一个IEnumerable<'a>
,其中'a是一个匿名类型,其中包含list1中的项目及其与list2中的相关项目。然后,您可以根据需要选择要使用的对象属性。
要将结果输出到具体列表,只需要调用.ToList()即可。你可以这样做
var list3 = joined.ToList();
// or
var list3 = (from Item1 in list1
join Item2 in list2
on Item1.Id equals Item2.Id // join on some property
select new { Item1, Item2 }).ToList();
要进行左连接以选择list1中的所有元素,即使list2中没有匹配,也可以执行类似这样的操作
var list3 = (from Item1 in list1
join Item2 in list2
on Item1.Id equals Item2.Id // join on some property
into grouping
from Item2 in grouping.DefaultIfEmpty()
select new { Item1, Item2 }).ToList();
这将为您提供一个列表,其中Item1等于第一个列表中的项目,Item2将等于第二个列表中的匹配项或默认值,对于引用类型将为null。
答案 1 :(得分:12)
以下是我提出的内容(基于this):
List<Contact> list3 = (from item1 in list1
join item2 in list2
on item1.ContactID equals item2.ContactID into g
from o in g.DefaultIfEmpty()
select o == null ? item1 :o).ToList<Contact>();
我最喜欢的部分是大鼻子笑脸
:o)
感谢您的帮助!
答案 2 :(得分:4)
以下是带有Linq群组加入的DotNetFiddle
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
class Order
{
public int Id;
public string Name;
public Order(int id, string name)
{
this.Id = id;
this.Name = name;
}
}
class OrderItem
{
public int Id;
public string Name;
public int OrderId;
public OrderItem(int id, string name, int orderId)
{
this.Id = id;
this.Name = name;
this.OrderId = orderId;
}
}
List<Order> orders = new List<Order>()
{
new Order(1, "one"),
new Order(2, "two")
};
List<OrderItem> orderItems = new List<OrderItem>()
{
new OrderItem(1, "itemOne", 1),
new OrderItem(2, "itemTwo", 1),
new OrderItem(3, "itemThree", 1),
new OrderItem(4, "itemFour", 2),
new OrderItem(5, "itemFive", 2)
};
var joined =
from o in orders
join oi in orderItems
on o.Id equals oi.OrderId into gj // gj means group join and is a collection OrderItem
select new { o, gj };
// this is just to write the results to the console
string columns = "{0,-20} {1, -20}";
Console.WriteLine(string.Format(columns, "Order", "Item Count"));
foreach(var j in joined)
{
Console.WriteLine(columns, j.o.Name, j.gj.Count() );
}
答案 3 :(得分:2)
看起来你真的不需要完全加入。您可以改为进行半连接,检查列表2中的每个联系人,看它是否包含在列表1中:
ContactCollection list3 = list2.Where(c => list1.Contains(c));
我不知道你的列表有多大,但请注意这种方法的复杂度为O(n m),除非list1被排序或支持快速查找(如在hashset中),在这种情况下它可能是与O(n log(m))一样高效或重写为合并连接并且为O(n)。