比较两个 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&lt;double&gt;,这是一个前期成本,可以让其他所有东西更便宜:

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&lt;T&gt;SortedList&lt;TKey, TValue&gt; 更改为SortedDictionary&lt;TKey, TValue&gt;,这将有助于更快地查找。

如果你喜欢使用Contains(),你必须实现IEquatable&lt;T&gt;,如果你想要性能,你必须Sort(),这需要类有IComparable&lt;T&gt;,然后执行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 项目中的主要内容,如果未能解决你的问题,请参考以下文章

VBA比较两个列表并删除不同列中具有重复值的行

python比较两个list之间的差异相同(差集交集并集)

Spark SQL Collect_list(struct) 保存为 json

两个list比较交集,差集

大数据量情况下高效比较两个list

java 对比两个list并取值