【问题标题】:DeepCompare a lot of items as ListDeepCompare很多项目为List
【发布时间】:2019-10-23 12:06:01
【问题描述】:

我有一个包含大约 15 个属性(姓名、年龄等)的简单数据模型。

我现在有 2 个列表:oldData 和 newData,我想比较它们并用它做点什么。问题是,列表很大(例如 100 万个项目),我对 foreach 的简单想法需要很多时间(约 6 分钟)。

如何更快?

  foreach (var item in oldItems)
            {
                try
                {

                    var actualItem = actualItems.Where(x => x.ObjectId == item.ObjectId).SingleOrDefault();
                    if (actualItem == null)
                    {
                        insertList.Add(item);
                        continue;
                    }

                    // Compare
                    var same = actualItem.ClientId == item.ClientId
                            && actualItem.Contract == item.Contract
                            && actualItem.CurrentNodeOwnerId == item.CurrentNodeOwnerId
                            && actualItem.ExternalInvoiceNo == item.ExternalInvoiceNo
                            && actualItem.InternalInvoiceNr == item.InternalInvoiceNr
                            && actualItem.InvoiceDate == item.InvoiceDate
                            && actualItem.NodeStart == item.NodeStart
                            && actualItem.ObjectNo == item.ObjectNo
                            && actualItem.OrderAmount == item.OrderAmount
                            && actualItem.OrderNo == item.OrderNo
                            && actualItem.PaymentAmount == item.PaymentAmount
                            && actualItem.PaymentCreatedDate == item.PaymentCreatedDate
                            && actualItem.PaymentNo == item.PaymentNo
                            && actualItem.PostingAmount == item.PostingAmount
                            && actualItem.PostingEnterDate == item.PostingEnterDate
                            && actualItem.ProcessWorkflowState == item.ProcessWorkflowState
                            && actualItem.RefInvoiceSource == item.RefInvoiceSource
                            && actualItem.RefInvoiceSourceId == item.RefInvoiceSourceId
                            && actualItem.Status == item.Status
                            && actualItem.TotalAmount == item.TotalAmount
                            && actualItem.VendorName == item.VendorName
                            && actualItem.VendorNo == item.VendorNo;

                    if (!same)
                    {
                        updateList.Add(item);
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(" Error when compare new ELO list with old ELO List in DWH Service: " + ex.Message + " | for Item: " + item.ObjectId, ex);
                }
            }

【问题讨论】:

  • 也许你应该把这个提交给CodeReview
  • @Innat3 它需要更多的上下文才能在代码审查中受到欢迎。我们无法有意义地审查当前代码。

标签: c# performance compare


【解决方案1】:

速度变慢可能是由于将旧项目与新项目匹配的行引起的。您可以通过为actualItems 创建一个Lookup 来加快查找速度。

进入循环前:

var actualItemsLookup = actualItems.ToLookup(x => x.ObjectId);

循环内部:

var actualItem = actualItemsLookup[item.ObjectId].SingleOrDefault();

来自文档:

Lookup<TKey,TElement> 类似于 Dictionary<TKey,TValue>。区别在于 Dictionary<TKey,TValue> 将键映射到单个值,而 Lookup<TKey,TElement> 将键映射到值的集合。

【讨论】:

    【解决方案2】:

    嗯, 如果您知道哪个属性使每个项目独一无二,这将有所帮助,否则您可以建立一些唯一的密钥。

    有记忆力 您可以从 O(n) *O(c) 开始,将最小列表存储到 dictionary/HashMap 中,其中键(唯一属性)、值(项目)。

    没有记忆 您可以对每个列表进行排序并使用 O(nLogn) 对它们进行一次遍历

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-01
      • 1970-01-01
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多