Linq:从两个不同的列表中找到类似的对象

时间:2014-09-15 14:25:18

标签: c# linq

我有两个单独的自定义对象列表。在这两个单独的列表中,两个列表之间可能存在一些相同的对象,但一个字段除外(" id")。我想知道一种查询这两个列表的智能方法来找到这种重叠。我附上了一些代码来帮助澄清。任何建议将不胜感激。

namespace ConsoleApplication1
{
class userObj
{
    public int id;
    public DateTime BirthDate;
    public string FirstName;
    public string LastName;
}

class Program
{
    static void Main(string[] args)
    {
        List<userObj> list1 = new List<userObj>();
        list1.Add(new userObj()
        {
            BirthDate=DateTime.Parse("1/1/2000"),
            FirstName="John",
            LastName="Smith",
            id=0
        });
        list1.Add(new userObj()
        {
            BirthDate = DateTime.Parse("2/2/2000"),
            FirstName = "Jane",
            LastName = "Doe",
            id = 1
        });
        list1.Add(new userObj()
        {
            BirthDate = DateTime.Parse("3/3/2000"),
            FirstName = "Sam",
            LastName = "Smith",
            id = 2
        });



        List<userObj> list2 = new List<userObj>();
        list2.Add(new userObj()
        {
            BirthDate =  DateTime.Parse("1/1/2000"),
            FirstName = "John",
            LastName = "Smith",
            id = 3
        });
        list2.Add(new userObj()
        {
            BirthDate = DateTime.Parse("2/2/2000"),
            FirstName = "Jane",
            LastName = "Doe",
            id = 4
        });


        List<int> similarObjectsFromTwoLists = null;
        //Would like this equal to the overlap. It could be the IDs on either side that have a "buddy" on the other side: (3,4) or (0,1) in the above case.

    }
}
}

5 个答案:

答案 0 :(得分:5)

我不知道你为什么要List<int>,我认为这就是你想要的:

var intersectingUser = from l1 in list1
                       join l2 in list2
                       on new     { l1.FirstName, l1.LastName, l1.BirthDate }
                       equals new { l2.FirstName, l2.LastName, l2.BirthDate }
                       select new { ID1 = l1.id, ID2 = l2.id };
foreach (var bothIDs in intersectingUser)
{
    Console.WriteLine("ID in List1: {0} ID in List2: {1}", 
                     bothIDs.ID1, bothIDs.ID2);
}

输出:

ID in List1: 0 ID in List2: 3
ID in List1: 1 ID in List2: 4

答案 1 :(得分:1)

您可以简单地加入这三个属性的列表:

 var result = from l1 in list1
              join l2 in list2
              on new {l1.BirthDate, l1.FirstName, l1.LastName} 
                    equals new {l2.BirthDate, l2.FirstName, l2.LastName}
              select new 
              {  
                 fname = l1.FirstName, 
                 name = l1.LastName, 
                 bday = l1.BirthDate
              };

不是仅在一个属性(列)上进行简单连接,而是创建两个匿名对象new { prop1, prop2, ..., propN},在其上执行连接。 在您的情况下,我们将获取除Id之外的所有属性,您希望忽略它们,并且瞧:

输出:

enter image description here

蒂姆一分钟打败了我

答案 2 :(得分:1)

您可以为IEqualityComparer<T>类实现自己的userObj,并使用它来运行两个列表之间的比较。这将是最高效的方法。

public class NameAndBirthdayComparer : IEqualityComparer<userObj>
{
    public bool Equals(userObj x, userObj y)
    {
        return x.FirstName == y.FirstName && x.LastName == y.LastName && x.BirthDate == y.BirthDate;
    }

    public int GetHashCode(userObj obj)
    {
        unchecked
        {
            var hash = (int)2166136261;

            hash = hash * 16777619 ^ obj.FirstName.GetHashCode();
            hash = hash * 16777619 ^ obj.LastName.GetHashCode();
            hash = hash * 16777619 ^ obj.BirthDate.GetHashCode();

            return hash;
        }
    }
}

你可以像这样使用comparer

list1.Intersect(list2, new NameAndBirthdayComparer()).Select(obj => obj.id).ToList();

答案 3 :(得分:1)

        var similarObjectsFromTwoLists = list1.Where(x => 
            list2.Exists(y => y.BirthDate == x.BirthDate && y.FirstName == x.FirstName && y.LastName == x.LastName)
         ).ToList();

这个更短,但是对于大型列表来说效率更高&#34; Intersect&#34;或者&#34;加入&#34;:

  var similarObjectsFromTwoLists = 
    list1.Join(list2, x => x.GetHashCode(), y => y.GetHashCode(), (x, y) => x).ToList();

(为userObj定义了GetHashCode())

答案 4 :(得分:1)

var query = list1.Join (list2, 
                obj => new {FirstName=obj.FirstName,LastName=obj.LastName, BirthDate=obj.BirthDate},
                innObj => new {FirstName=innObj.FirstName, LastName=innObj.LastName, BirthDate=innObj.BirthDate},
                (obj, userObj) => (new {List1Id = obj.id, List2Id = userObj.id}));

foreach (var item in query)
    {
    Console.WriteLine(item.List1Id + " " + item.List2Id);
    }