【问题标题】:comparing two lists with LINQ用 LINQ 比较两个列表
【发布时间】:2014-08-28 18:22:19
【问题描述】:

假设我有这两个 Person 列表。 Person 对象具有 FirstName、LastName 和 Age 属性。

列表 A

大卫·史密斯,38 岁 大卫史密斯,38 岁 苏珊·约翰逊,23 岁

列表 B

大卫·史密斯,38 岁 大卫史密斯,38 岁 苏珊约翰逊,23 岁 丹尼尔·华莱士,55 岁

我想通过比较三个属性来查看 A 是否是 B 的子集。不,在这种情况下,我没有每个人的唯一 ID。

编辑:列表 A 中可能有重复项(David Smith,38 岁)。列表 B 应该具有重复项才能成为 B 的超集。

【问题讨论】:

  • 还有其他属性吗? Person 是否恰当地实现了IEquatable<Person>
  • 我的班级不完全是人。但是不,我正在阅读 IEquatable。那么我使用什么 LINQ 运算符呢?包含?

标签: c# linq


【解决方案1】:

一旦你有了一个实现IEquatable<T>IEqualityComparer<T> 的类,剩下的就很容易用ExceptAny 来完成:

if (collectionA.Except(collectionB).Any())
{
    // There are elements in A which aren't in B
}

if (collectionA.Except(collectionB, equalityComparer).Any())
{
    // There are elements in A which aren't in B
}

编辑:如果有重复,您可能希望对每个集合进行分组,然后检查计数:

var groupedA = collectionA.GroupBy(p => p,
                                   (Value, g) => new { Value, Count = g.Count() });
var groupedB = collectionB.GroupBy(p => p,
                                   (Value, g) => new { Value, Count = g.Count() });
var extras = from a in groupedA
             join b in groupedB on a.Value equals b.Value into match
             where !match.Any() || a.Count > match.First().Count
             select a;

// ListA has at least one entry not in B, or with more duplicates than in B
if (extras.Any())
{
}

这实在是太可怕了……

【讨论】:

  • 这适用于重复项吗?我修复了原始帖子以包含重复项。要使列表 B 有资格成为 A 的超集,它需要具有所有重复项。
  • 所以您的意思是,如果列表 A 包含 3 次“David Smith, 38”,那么列表 B 也需要至少包含 3 次?
  • 是的。我知道这是一个可怕的例子。但就我的情况而言,B 需要包含所有重复项。
  • @user79284:尝试在我的答案中进行编辑 - 但可能有更简单的方法。 (将来,请在开始时包括这样的关键详细信息。)
【解决方案2】:

如果Person 没有实现IEquatable<Person>,“蛮力”方法将是:

var isSubset = listA.All(pa => listB.Any(pb => pb.FirstName == pa.FirstName &&
                                               pb.LastName == pa.LastName &&
                                               pb.Age == pb.Age
                                        ) 
                        )

【讨论】:

    【解决方案3】:

    你可以使用join

    var l1 = new List<Person>();//Subset 
    var l2 = new List<Person>();//Set of all values
    
    var res = from l1 in lst1
                          join l2 in lst2 
                          on l1.Value equals l2.Value
                          select new { result = l1 };
    

    并比较count。如果相等,则Set包含子集

    bool flag = res.Count()==lst1.Count();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      相关资源
      最近更新 更多