LINQ加入2列表<t> s </t>

时间:2010-04-27 18:40:24

标签: c# linq

前言:我不明白这是做什么的:

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中的所有项目替换为list1list2项中的项目list1中的项目ID。结果列表(list2)应在list3包含相同数量的项目。

我觉得我没有任何意义。所以,请在评论中提问,我会尽力澄清。

4 个答案:

答案 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)。