【问题标题】: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

提前致谢:)

【问题讨论】:

标签: c# list struct find contains


【解决方案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:如果性能如此关键,您应该在问题中提及这一点 - 包括给出正确答案的解决方案的基准和具体的性能标准。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 2021-10-22
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多