DeepCompare много предметов, как список - PullRequest
0 голосов
/ 23 октября 2019

У меня есть простая модель данных с примерно 15 свойствами (имя, возраст и т. Д.).

Теперь у меня есть 2 списка: oldData и newData, которые я хочу сравнить и что-то с ними сделать. Проблема в том, что списки огромны (например, 1 миллион элементов), и мое простое представление о 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);
                }
            }

Ответы [ 2 ]

1 голос
/ 23 октября 2019

Замедление, вероятно, вызвано линией, которая сопоставляет старые элементы с новыми. Вы можете ускорить поиск, создав Lookup для actualItems.

Перед входом в цикл:

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

Внутри цикла:

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

Из документации:

A Lookup<TKey,TElement> напоминает Dictionary<TKey,TValue>. Разница в том, что Dictionary<TKey,TValue> отображает ключи на отдельные значения, тогда как Lookup<TKey,TElement> отображает ключи на наборы значений.

0 голосов
/ 23 октября 2019

Хорошо, если вы знаете, какое свойство делает каждый элемент уникальным, это поможет, в противном случае вы можете создать какой-то уникальный ключ.

с памятью вы можете начать с O (n) *O (c) путем сохранения наименьшего списка в словарь / HashMap с ключом (уникальное свойство), значением (элемент).

без памяти вы можете отсортироватькаждый список и сделать один проход по обоим из них с O (nLogn)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...