【问题标题】:Get matched and unmatched elements from 2 lists从 2 个列表中获取匹配和不匹配的元素
【发布时间】:2016-07-02 20:56:12
【问题描述】:

我有一个名为Privileges的类,具有以下属性int UserId,string FormName,string CompName,int Privilege

我有 2 个 Privileges 类型列表,其值不同,如下例所示

List<Privileges> list1 = new List<Privileges>(){
            new Privileges(){UserId= 1,FormName="Form1",CompName="Button1",Privilege=2},
            new Privileges(){UserId= 2,FormName="Form1",CompName="Button3",Privilege=3},
            new Privileges(){UserId= 3,FormName="Form2",CompName="Button2",Privilege=2}
        };

        List<Privileges> list2 = new List<Privileges>(){
            new Privileges(){UserId= 5,FormName="Form1",CompName="Button1",Privilege=2},
            new Privileges(){UserId= 2,FormName="Form1",CompName="Button3",Privilege=4},
            new Privileges(){UserId= 4,FormName="Form2",CompName="Button2",Privilege=3}
        };

我想做3个功能
我做了第一个返回两个列表之间的匹配元素 结果如下

{UserId= 2,FormName="Form1",CompName="Button3",Privilege=3}

第二个函数应该返回存在于第一个列表中而不是第二个列表中的元素,结果如下

{UserId= 1,FormName="Form1",CompName="Button1",Privilege=2},
{UserId= 3,FormName="Form2",CompName="Button2",Privilege=2}

第三个函数应该返回存在于第二个列表中而不是第一个列表中的元素,结果如下

{UserId= 5,FormName="Form1",CompName="Button1",Privilege=2},
{UserId= 4,FormName="Form2",CompName="Button2",Privilege=3}

无论privilege 的值是什么,匹配子句都应该比较UserId,FormName,CompName 的值。

you can check my code snippet here

【问题讨论】:

标签: c# linq join


【解决方案1】:

您不必为这些(以及更多)任务编写任何复杂的 LINQ 语句。只需定义一个IEqualityComparer,一切都会变得简单得离谱:

class PrivilegesComparer : IEqualityComparer<Privileges>
{
    public bool Equals(Privileges x, Privileges y)
    {
        return x.UserId == y.UserId
               && x.FormName == y.FormName
               && x.CompName == y.CompName;
    }

    public int GetHashCode(Privileges obj)
    {
        return (obj.UserId + obj.FormName + obj.CompName).GetHashCode();
    }
}

用法:

var comparer = new PrivilegesComparer();
var intersect = list1.Intersect(list2, comparer);
var l1Exceptl2 = list1.Except(list2, comparer);
var l2Exceptl1 = list2.Except(list1, comparer);

分别代表你的第一个、第二个和第三个函数。

这与为每个单独的任务编写复杂的 LINQ 语句完全不同。

【讨论】:

  • 喜欢这个通用的解决方案,比我的多
  • 我喜欢这个解决方案,但你能告诉我如何在相交的情况下给出 Privilege 的具体值
  • 只需在列表中使用 Where。
【解决方案2】:

list1 中的元素不在list2

var itemsInList1NotInList2 = list1.Where(l1 => !list2.Any(l2 => l1.UserId == l2.UserId && l1.FormName == l2.FormName && l1.CompName == l2.CompName)).ToList();

list2 中的元素不在list1

var itemsInList2NotInList1 = list2.Where(l2 => !list1.Any(l1 => l1.UserId == l2.UserId && l1.FormName == l2.FormName && l1.CompName == l2.CompName)).ToList();

【讨论】:

  • 我想指出这个解决方案效率很低。更有效的解决方案可能应该使用HashSet.Except,而HashSet 应该使用custom comparer,它将忽略privilege 的值。
  • 我会看到它,但目前我会使用这个解决方案,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多