按特定属性比较两个列表

Posted

技术标签:

【中文标题】按特定属性比较两个列表【英文标题】:Compare two Lists by specific properties 【发布时间】:2021-08-29 12:10:38 【问题描述】:

我在一个列表中有一个列表。我需要两个将 sub_List 的两个属性与第三个列表进行比较。

类:

public class Human

    public string FirstName get; set; 
    public string LastName get; set; 
    public List<Clothing> clothings  get; set; 


public class Clothing

    public string ClothingID get; set; 
    public string Garment get; set; 
    public string Color get; set; 


public class CurrentClothes

    public string Garment get; set; 
    public string Color get; set; 

伪代码:

public List<Human> humans = new List<Human>()

    new Human
    
        FirstName="Karl",
        LastName="Karlson"
        clothings=new List<Clothing>()
        
            new Clothing
            
                ClothingID="1",
                Garment="T-Shirt",
                Color="pink"
            ,
            new Clothing
            
                ClothingID="11",
                Garment="Pant",
                Color="white"
            ,
            new Clothing
            
                ClothingID="111",
                Garment="Shoes",
                Color="black"
            
        
    ,
    new Human
    
        FirstName="Paula",
        LastName="Paulson"
        clothings=new List<Clothing>()
        
            new Clothing
            
                ClothingID="2",
                Garment="T-Shirt",
                Color="red"
            ,
            new Clothing
            
                ClothingID="22",
                Garment="Pant",
                Color="blue"
            ,
            new Clothing
            
                ClothingID="222"
                Garment="Shoes",
                Color="black"
            
        
    
;
    
public List<CurrentClothes> currentclothes = new List<CurrentClothes>()

    new CurrentClothes
    
        Garment="Pant",
        Color="blue"
    ,
    new CurrentClothes
    
        Garment="T-Shirt",
        Color="red"
    ,
    new CurrentClothes
    
        Garment="Shoes",
        Color="black"
    


var human = humans.Where(x=>x.clothings.Equals(currentClothes));

问题是,我如何比较当前的衣服是否与某些人的衣服相匹配。有没有 Linq 选项?

我添加了一个示例。在此示例中,有两个人。卡尔和保拉。现在的衣服是确定的。现在我想要人类如何匹配当前的衣服。在这种情况下是宝拉。

【问题讨论】:

你能给我们提供预期输出的样本数据吗?对我来说,这实际上很不清楚 Enumerable.Any 你在找什么? 你叫什么“比较”你如何定义它们是否相等?也许你应该实现IEquatable 您应该重写 Clothing 类的 Equals 方法。请参阅此处的文档,您将知道如何将其与 CurrentClothes 进行比较。 docs.microsoft.com/en-us/dotnet/api/… 。通过这种方式,您可以重新定义您的标准,了解如何始终比较这两个类并定义您的平等标准 @Zinov 您能否在我的示例中提供一个代码示例如何覆盖 equal 方法并使用 ist 从列表中获取正确的人? 【参考方案1】:

我会做以下事情

public class Human

    public string FirstName  get; set; 
    public string LastName  get; set; 
    public List<Clothing> clothings  get; set; 


public class Clothing : CurrentClothes

    public string ClothingID  get; set; 


public class CurrentClothes : IEquatable<CurrentClothes>

    public string Garment  get; set; 
    public string Color  get; set; 

    public override bool Equals(object obj) => ReferenceEquals(this, obj) || obj is CurrentClothes other && Equals(other);
    public bool Equals(CurrentClothes other)
    
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Garment == other.Garment && Color == other.Color;
    
    public override int GetHashCode() => HashCode.Combine(Garment, Color);

比这样使用它:

var currentclothesAsHashSet = currentclothes.ToHashSet();
var human = humans.Where(x => x.clothings.OfType<CurrentClothes>().ToHashSet().SetEquals(currentclothesAsHashSet));
foreach (var human1 in human)

    Console.WriteLine(human1.FirstName);

这个使用的方法

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.iset-1.setequals

查看Human.clothings 是否与currentclothes 相同。

这里有一个演示: https://dotnetfiddle.net/tS72Wt

编辑:

正如评论中所指出的,如果currentClothes 只能是数据的一个子集,您可能需要将SetEquals 更改为Except

就像这个演示演示的那样:

https://dotnetfiddle.net/FZg85Z

【讨论】:

只是对@T0bi 的一个小评论,从目前的衣服与人类所穿的完全一样的问题中不清楚,如果不是并且当前的衣服可能指定比实际更多的衣服,你可以像这样使用 IsSupersetOf 而不是 SetEquals: ... var human = human.Where(x =>currentClothesAsHashSet.IsSupersetOf(x.clothings.OfType().ToHashSet())); @DorLugasi-Gal - contains 是错误的,因为人类 Frank 和 Paula 都包含“Shoes / black”,只有 Paula 应该是阳性结果。 - 我唯一能看到的是 currentClothes 只是数据的一个子集,例如。只有 2 个条目,但人类有 3 个服装条目而不是 SetEquals 是错误的,它需要更改为 !subset.Except(superset).Any() - 就像这里解释的那样:***.com/questions/407729/… @DorLugasi-Gal,是的,可能还有更多,例如(示例 + 新衣服“Head”),那么它不匹配。 我是否理解正确,如果我继承某些东西,我可以更改仅比较继承的相同方法? @RandRandom 感谢您的回答和提供的示例。我检查了dotnetfiddle.net/FZg85Z 链接,我发现当我删除一个 currentclothing 对象时,它也显示了 paula。我现在就试一试,希望能找到解决问题的方法。【参考方案2】:

你可以像这样使用Any

    humans.clothings.Where(x => 
       currentClothes.Any(s => 
        s.Color.Equals(x.Color) && s.Garment.Equals(x.Garment)
       )
    ).ToList();

查看this 获取 .netFiddle 演示

【讨论】:

似乎不符合要求,因为您返回的是服装清单而不是人类。并且似乎Any 不正确,更像是只返回返回与ALL 衣服匹配的人 我知道,我会更新这个@RandRandom

以上是关于按特定属性比较两个列表的主要内容,如果未能解决你的问题,请参考以下文章

使用 LINQ 获取两个比较列表的结果并根据结果更改列表中的属性

比较两个 Anagrams 列表 - Java

递归比较两个列表

比较具有布尔属性的两个通用项,如果其中任何一个返回true,则返回结果通用列表中的true

使用LINQ按字母顺序比较字符串

如何将python中的两个列表与if loc条件进行比较