基于嵌套列表中包含的 id 元素比较两个通用列表的最有效方法 (C#)

Posted

技术标签:

【中文标题】基于嵌套列表中包含的 id 元素比较两个通用列表的最有效方法 (C#)【英文标题】:Most efficient way to compare two generic lists based on id elements contained within nested list (C#) 【发布时间】:2021-01-28 14:49:18 【问题描述】:

我有两个通用的项目列表,每个列表都包含一个供应商列表及其 ID:

List<ExisitingItems>
    List<Suppliers>

List <PotentialMatches>
    List<Suppliers>

Suppliers
    SupplierId
    Name

我需要根据嵌套的供应商 ID 和名称,将现有项目列表与潜在匹配项列表进行比较。

我目前将这两个列表与所需的结果进行比较,如下所示:

  foreach (var potentialMatch in _potentialMatches)
            
foreach (var supplier in potentialMatch.Suppliers)
                
                    var match = ExistingItems.Find
                       (e => e.Suppliers.Any
                        (s => s.SupplierId == supplier.SupplierItemId && s.Name == supplier.Name));

//Do stuff with match
                
             

但是,当处理大于 500k 的大量记录时,效率不高且执行速度非常慢。

我怎样才能更有效地执行相同类型的比较?

【问题讨论】:

【参考方案1】:

您当前的算法似乎是O(n*m*s*s),其中 n = 现有项目的数量,m = 潜在匹配的数量,s = 每个现有项目/PotentialMatch 的平均供应商数量。您可以通过使用哈希集来匹配供应商,将运行时间减少到O(n*m*s)

通用版本如下所示

public static IEnumerable<(T1, T2)> SetJoin<T1, T2, TKey>(
        IEnumerable<T1> t1s,
        IEnumerable<T2> t2s,
        Func<T1, IEnumerable<TKey>> t1Key,
        Func<T2, IEnumerable<TKey>> t2Key) where TKey : IEquatable<TKey>
    
        foreach (var t1 in t1s)
        
            var t1Keys = new HashSet<TKey>(t1Key(t1));
            foreach (var t2 in t2s)
            
                // t2Key(t2) would be called many times, 
                // might be worth pre-computing it for each t2.
                if (t2Key(t2).Any(t1Keys.Contains))
                
                    yield return (t1, t2);
                
                
        
    

然后这样称呼它

SetJoin<ExistingItems, PotentialMatches, int>(
              existingItems, 
              potentialMatches,
              e=> e.Suppliers.Select(s => s.Id),
              p => p.Suppliers.Select(s => s.Id))

此外,虽然 linq 可以生成紧凑且漂亮的代码,但如果性能很重要,使用常规循环编写等效逻辑通常会更快。

【讨论】:

以上是关于基于嵌套列表中包含的 id 元素比较两个通用列表的最有效方法 (C#)的主要内容,如果未能解决你的问题,请参考以下文章

dplyr:如何以编程方式完整连接列表列表中包含的数据帧?

如何处理版本列表中包含的字符串导致的错误,按StrictVersion排序?

R - 子集列表data.frames由矢量值

创建布尔数据框,显示列表字典中每个元素的存在

从列表中包含的字符串命名 df 列

如何将嵌套列表中的值转换为集合?