比较两个 struct List 并查找 list1 的项目是不是出现在 C# 中的 list2 项目中
Posted
技术标签:
【中文标题】比较两个 struct List 并查找 list1 的项目是不是出现在 C# 中的 list2 项目中【英文标题】:Compare two struct List and find if item of list1 appears in item of list2 in C#比较两个 struct List 并查找 list1 的项目是否出现在 C# 中的 list2 项目中 【发布时间】:2020-12-12 09:02:52 【问题描述】:我有两个记录结构和两个列表如下:
public struct gtAliasRecType : ICloneable
public int lRecordNum;
public double dLocationCd;
public struct gtCVARecType : ICloneable
public double dLocationCd;
static public List<gtCVARecType> LCVARec = null;
static public List<gtAliasRecType> LAliasRec = null;
现在我想迭代“LAliasRec”列表并查找“LCVARec”列表中是否存在类似的“dLocationCd”。
我尝试使用 list1 的“包含”和“查找”功能,但最终出错。
public static void XYZ()
gtAliasRecType uAliasRec = gtAliasRecType.CreateInstance();
gtCVARecType uCVARec = gtCVARecType.CreateInstance();
for (int i = 0; i < LAliasRec.Count; i++)
uAliasRec = LAliasRec[i];
//trying Find method
gtCVARecType c1 = LCVARec.Find(uAliasRec.dLocationCd);
//trying Contains method
bool nReturn = LCVARec.Contains( uAliasRec.dLocationCd );
但是,我遇到了“无法从 'double' 转换为 'gtCVARecType' 错误。
Contains & Find
提前致谢:)
【问题讨论】:
请向我们展示您尝试过的完整代码,以及您看到的具体错误。基本上,请提供minimal reproducible example。 (我还要注意,像这样的可变结构通常是一个坏主意——我通常还建议使用属性而不是公共字段,并遵循 .NET 命名约定。) 您能分享一下您是如何尝试使用包含和查找的吗?您在这方面面临什么问题? 您可以使用 LINQ。检查docs.microsoft.com/en-us/dotnet/csharp/linq/perform-inner-joins 这能回答你的问题吗? Compare Two Lists Via One Property Using LINQ 你好@ChetanRanpariya,我已经更新了快照 【参考方案1】:您不能使用Contains
来查找不同类型的项目。您可以使用Find
,但我个人会使用LINQ Any
方法:
foreach (var uAliasRec in LAliasRec)
bool nReturn = LCVARec.Any(rec => rec.dLocationCd == uAliasRec.dLocationCd);
// Presumably do something with nReturn
如果列表很大,您可能需要先为所有位置创建一个HashSet<double>
,这是一个前期成本,可以让其他所有东西更便宜:
HashSet<double> locations = new HashSet<double>(LCVARec.Select(rec => rec.dLocationCd));
foreach (var uAliasRec in LAliasRec)
bool nReturn = locations.Contains(uAliasRec.dLocationCd);
// Presumably do something with nReturn
顺便说一句,我强烈建议您开始遵循常规的 .NET 命名约定。在目前的形式下,您的代码对于习惯于常规 C# 代码的任何人来说都将非常难以使用。
【讨论】:
【参考方案2】:您可以使用 LINQ 和 Inner join 来查找两个列表的交集。
var query = from lcva in LCVARec
join lAlias in LAliasRec on lcva.dLocationCd equals lAlias.dLocationCd
select lcva;
Console.WriteLine(query.Count()); //prints number of matching items.
更新
如果您可以将List<T>
的SortedList<TKey, TValue>
更改为SortedDictionary<TKey, TValue>
,这将有助于更快地查找。
如果你喜欢使用Contains()
,你必须实现IEquatable<T>
,如果你想要性能,你必须Sort()
,这需要类有IComparable<T>
,然后执行BinarySearch
参考:https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netcore-3.1#remarks
【讨论】:
您好@Ramesh,我正在解决性能问题,与“查找”或“包含”功能相比,使用 LINQ 查询会降低性能。因为我的列表中可能有多达 70k 的项目。 1.如果性能很关键,为什么不以 dLocatoinCd 为键将它们存储在字典中? 2.您是否测量了 LINQ 查询以确认性能是否受到影响?这可能与 forloop + Find / Contains 相同 @AbhishekSingh - 请查看更新后的答案【参考方案3】:用Intersect
怎么样
var results = LAliasRec
.Select(x => x.dLocationCd)
.Intersect(LCVARec.Select(x => x.dLocationCd));
bool exists = results.Count() > 0;
Select
只有双精度值,并得到相交的值。如果Count
大于 0,则你得到了相互的属性值。
【讨论】:
您好@Berkay,感谢您的快速回复。但是,我正在处理性能问题,与“查找”或“包含”功能相比,使用“相交”和“选择”会降低性能。您的代码运行良好,但与列表“dLocationCd”值顺序相比,它甚至以某种特定顺序对“dLocationCd”值进行排序。 @AbhishekSingh:如果性能如此关键,您应该在问题中提及这一点 - 包括给出正确答案的解决方案的基准和具体的性能标准。以上是关于比较两个 struct List 并查找 list1 的项目是不是出现在 C# 中的 list2 项目中的主要内容,如果未能解决你的问题,请参考以下文章