检查一个列表元素中的元素是不是存在于另一个列表中
Posted
技术标签:
【中文标题】检查一个列表元素中的元素是不是存在于另一个列表中【英文标题】:Check if elements from one list elements present in another list检查一个列表元素中的元素是否存在于另一个列表中 【发布时间】:2022-01-06 08:20:49 【问题描述】:我有 2 个 c# 类 -
class ABC
string LogId;
string Name;
class XYZ
string LogId;
string Name;
class Checker
public void comparelists()
List<ABC> lstABC =new List<ABC>();
lstABC.Add(new ABC...);
lstABC.Add(new ABC...);
lstABC.Add(new ABC...);
List<XYZ> lstXYZ =new List<XYZ>();
lstXYZ.Add(new XYZ...);
lstXYZ.Add(new XYZ...);
lstXYZ.Add(new XYZ...);
var commonLogId = lstABC
.Where(x => lstXYZ.All(y => y.LogId.Contains(x.LogId)))
.ToList();
从代码中可以看出,我想从 lstABC 中获取 lstXYZ 中存在的所有 logid。
例如。 lstABC 有 ->
LogId="1", Name="somename1"
LogId="2", Name="somename2"
LogId="3", Name="somename3"
LogId="4", Name="somename4"
LogId="5", Name="somename5"
lstXYZ 有 ->
LogId="1", Name="somename11"
LogId="2", Name="somename22"
LogId="3", Name="somename33"
LogId="8", Name="somename8"
LogId="9", Name="somename9"
然后 lstXYZ 中存在的 lstABC 中的所有 logid 都是 - 1,2,3 ;所以所有这些记录都应该被获取。
但使用以下 linq 查询 -
var commonLogId = lstABC
.Where(x => lstXYZ.All(y => y.LogId.Contains(x.LogId)))
.ToList();
正在获取/选择 0 条记录。
【问题讨论】:
【参考方案1】:通过Any()
接近
var res = lstABC.Where(x => (lstXYZ.Any(y => y.LogId == x.LogId))).Select(x => x.LogId);
https://dotnetfiddle.net/jRnUwS
另一种方法是Intersect()
,这对我来说感觉更自然
var res = lstABC.Select(x => x.LogId).Intersect(lstXYZ.Select(y => y.LogId));
https://dotnetfiddle.net/7iWYDO
【讨论】:
【参考方案2】:您使用了错误的 LINQ 函数。试试Any()
:
var commonLogId = lstABC
.Where(x => lstXYZ.Any(y => y.LogId == x.LogId))
.ToList();
还要注意与Contains()
的id 比较是错误的。只需改用==
。
All()
检查列表中的所有元素是否满足指定条件。另一方面,Any()
仅检查是否至少有一个元素存在。
请注意,当两个列表都很大时,您的实现将非常缓慢,因为它的运行时复杂性随着要比较的元素数量呈二次方增长。更快的实现将使用专门为此目的创建和优化的Join()
:
var commonLogIds = lstABC
.Join(
lstXYZ,
x => x.LogId, // Defines what to use as key in `lstABC`.
y => y.LogId, // Defines what to use as key in `lstXYZ`.
(x, y) => x) // Defines the output of matched pairs. Here
// we simply use the values of `lstABC`.
.ToList();
【讨论】:
【参考方案3】:与完全不同的类型相交似乎很不自然,所以我很想连接共性并写一个EqualityComparer
:
class ABC : ILogIdProvider
public string LogId get;set;
public string Name;
class XYZ : ILogIdProvider
public string LogIdget;set;
public string Name;
interface ILogIdProvider
string LogIdget;
class LogIdComparer : EqualityComparer<ILogIdProvider>
public override int GetHashCode(ILogIdProvider obj) => obj.LogId.GetHashCode();
public override bool Equals(ILogIdProvider x, ILogIdProvider y) => x.LogId == y.LogId;
那么你可以更自然地Intersect
列表:
var res = lstABC.Intersect(lstXYZ, new LogIdComparer());
现场示例:https://dotnetfiddle.net/0Tt6eu
【讨论】:
以上是关于检查一个列表元素中的元素是不是存在于另一个列表中的主要内容,如果未能解决你的问题,请参考以下文章
C# 从 List<T> 中选择存在于另一个列表中的所有元素
在 Presto 中,如何检查我通过子查询获取的列表中是不是存在数组中的元素