微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过linq将列表中的每个值与另一个列表进行比较

如何解决如何通过linq将列表中的每个值与另一个列表进行比较

我有两个列表:

ListA ListB

Name Name
marc marc
micheal micheal
Jolie Jolie

我想比较这两个列表A和B,如果它们具有相同的名称,则应该返回true。如果一个列表具有与其他列表不同的值,则应返回false;如果一个列表具有2个值,而另一个具有3个值,则也应返回false。 即使它们具有相同的值,这种特征也会使我始终错误

var SameNames = ListA.All(x => ListB.All(y => y.Name.Equals(x.Name)));

我做错了吗?请

解决方法

var SameNames = ListA.All(x => ListB.All(y => y.Name.Equals(x.Name)));

您在此处写的是一个要求,即A中的 all 名称必须与B中的 all 名称相匹配。这显然与示例数据相冲突,例如A中的“ Marc”不等于来自B的“朱莉”。

如果A和B总共仅包含一个不同的名称,则您当前的代码将仅返回true。这对于您要解决的问题没有任何意义。


您实际上要解决的问题是,如果A中的所有名称在B中都匹配一个。可以通过以下方式实现:

var sameNames = listA.All(a => listB.Any(b => b.Name.Equals(a.Name)));

请注意Any。如果找到(至少)一个匹配项,则返回true。这与All不同,var listA = new List<string>() { "Andy","Bobby","Cindy" }; var listB = new List<string>() { "Andy","Cindy","David" }; var SameNames = listA.All(a => listB.Any(b => b.Name.Equals(a.Name))); 仅在B中的所有值匹配时返回true。

但是,这还不够。现在,您已经确定A的所有名称都出现在B中,但是B仍然有可能包含更多不在A中的名称。以下面的示例为例:

SameNames

true将是var listA_in_listB = listA.All(a => listB.Any(b => b.Name.Equals(a.Name))); var listB_in_listA = listB.All(b => listA.Any(a => a.Name.Equals(b.Name))); var sameNames = listA_in_listB && listB_in_listA; ,但这是因为您只有一个方向。您需要双向检查:

var listA_in_listB = listA.All(a => listB.Any(b => b.Name.Equals(a.Name)));
var sameLength = listA.Length == listB.Length;

var sameNames = listA_in_listB && sameLength;

这将为您提供所需的结果。


请注意,如何处理此问题还有其他几种方式。

如果您可以保证每个列表都不包含重复项,那么您可以简单地执行一项检查,然后确认列表的长度相同,而不必两次进行相同的检查:

                  WEEK_BEG_DT  ...             WEEK_BEG_DT      OHTER
0                 2013-09-29  ...              2013-09-29       a
1                 2013-06-23  ...              2013-09-29       b
2                 2012-04-28  ...              2013-09-29       c
3                 2013-01-06  ...              2013-09-29       d
4                 2013-06-16  ...              2013-09-29       e

这效率更高,但确实需要知道您的名字在每个列表中都是唯一的。

,

有一篇关于Microsoft in here

的文章

您应该创建函数以比较每个值。变量不是解决方案。

使功能类似于示例:

{
    static void Main()  
    {  
        // Create the IEnumerable data sources.  
        string[] names1 = System.IO.File.ReadAllLines(@"../../../names1.txt");  
        string[] names2 = System.IO.File.ReadAllLines(@"../../../names2.txt");  
  
        // Create the query. Note that method syntax must be used here.  
        IEnumerable<string> differenceQuery =  
          names1.Except(names2);  
  
        // Execute the query.  
        Console.WriteLine("The following lines are in names1.txt but not names2.txt");  
        foreach (string s in differenceQuery)  
            Console.WriteLine(s);  
  
        // Keep the console window open in debug mode.  
        Console.WriteLine("Press any key to exit");  
        Console.ReadKey();  
    }  
}  
/* Output:  
     The following lines are in names1.txt but not names2.txt  
    Potra,Cristina  
    Noriega,Fabricio  
    Aw,Kam Foo  
    Toyoshima,Tim  
    Guy,Wey Yuan  
    Garcia,Debra  
     */  
,

您可以使用var SameNames = ListA.SequenceEquals(ListB)。这将使用对象中定义的默认等于。如果两个对象中的任何一个为空,它将引发异常。因此,请确保您的列表不为空。

等于实现

class YourListItem {
   public string Name { get; set; }

   public override bool Equals(object obj)
   {
        if(obj is YourListItem other) {
             return this.Name == other.Name;
        }
        return false;
   }
   
   public override int GetHashCode() => this.Name.GetHashCode();
}

如果您需要的定制比较逻辑不能真正“适合”对象equals方法,或者您需要多个不同的相等实现。您可以创建另一个为您的类型实现IEqualityComparer的类,并将其作为第二个参数var SameNames = ListA.SequenceEquals(ListB,new MyEqualityComparer())传递。

平等比较器

class MyEqualityComparer: IEqualityComparer<YourListItem> {
    public bool Equals(YourListItem first,YourListItem second) {
         return first.Name == second.Name;
    }
    public int GetHashCode(YourListItem obj) => obj.Name.GetHashCode();
}

注意:覆盖Equals时,还应该始终实现GetHashCode。如果哈希码不相同,则它就像一个较短的等号(从某种意义上来说)等号是多余的,不需要执行。如果HashCode不同,则许多使用EqualityComparers或Equals的预构建方法将无法运行Equals。默认的HashCode是Object引用,因此它会错误地匹配两个列表,使它们实际上不应该等于Equal(如果您不覆盖HashCode)。对于您的HashCode实现,为大多数对象选择一个您认为不同的字段。如果您有一个像这样的微小对象,它看起来很愚蠢,但是您可以拥有庞大的对象,这些对象具有复杂的Equals实现或缓慢的基于通用反射的相等性检查。因此,在大多数情况下,能够在HashCode不相同的情况下完全跳过Equality检查是很重要的。

,

如果订单应该相关:

bool result = Enumerable.SequenceEquals<string>(ListA,ListB);

如果订单无关紧要:

bool result = new HashSet<string>(ListA).SetEquals(ListB);

这样做在LINQ中太复杂了,只是调整过头,此时您可以使用ForEachs。如果您想要一个简单干净的解决方案,那么这些都适合您。

问候

,

以下是满足您要求的代码。

var isEqual = ListA.OrderBy(o=>o.Name).SelectMany(x=>x.Name).SequenceEqual(ListB.OrderBy(o=>o.Name).SelectMany(x => x.Name));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。