按特定属性比较两个列表
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.OfTypeSetEquals
是错误的,它需要更改为 !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 获取两个比较列表的结果并根据结果更改列表中的属性