C # / .NET сравнивает два больших списка и находит недостающие элементы в обоих списках

2

так что в основном у меня есть два больших списка, например:

public class Items
{
 public string ItemID { get; set; }
}


var oldList = new List<Items>(); // oldList

var newList = new List<Items>(); // new list

Оба списка очень велики, и простой двойной foreach не будет достаточным из-за плохого времени выполнения, если они оба велики (более 30 секунд).

В предыдущем вопросе, который я задал для stackoverflow, я получил ответ о том, как сравнить эти два одинаковых списка и выяснить, какие элементы имеют различный параметр QuantitySold, а затем сохранить его в третьем списке с именем "DifferentQuantityItems", например:

var differentQuantityItems =
    (from newItem in newList
     join oldItem in oldList on newItem.ItemID equals oldItem.ItemID
     where newItem.QuantitySold != oldItem.QuantitySold
     select newItem).ToList();

Теперь я хотел бы получить из этих двух списков следующее:

- A list of items that are present in newList, but not in oldList

- A list of items that are present in oldList, but not in newList

Как мне этого добиться? Кто-нибудь может мне помочь?

PS То, как я "узнал", что ни один из элементов отсутствует в одном из списков, это свойство "ItemID"...

  • 0
    Кто-нибудь, ребята? знак равно
  • 0
    Вы можете попробовать intersection и union LINQ docs.microsoft.com/en-us/dotnet/api/…
Показать ещё 5 комментариев
Теги:
linq

5 ответов

1
Лучший ответ

отредактированный

Кроме будет работать намного быстрее. Здесь вы можете прочитать о его исполнении

var missedOld = oldList.Except(newList, new ItemsEqualityComparer());
var oldList= oldList.Except(missedOld, new ItemsEqualityComparer());

Старый ответ

Два разных списка с отсутствующими элементами

var missedOld = oldList.Where(x => !newList.Select(i => i.ItemID).Contains(x.ItemID)) 
var missedNew = newList.Where(x => !oldList.Select(i => i.ItemID).Contains(x.ItemID))

Все пропущенные предметы в одном списке:

oldList.Concat(newList).GroupBy(x => x.ItemID).Where(x => x.Count() < 2).Select(x => x.Value).ToList()
  • 0
    Разве вы не должны создавать новую переменную и хранить в ней новые значения?
  • 0
    PS Я хотел бы, чтобы отсутствующие элементы из обоих списков были разделены на два разных списка ... = d
Показать ещё 8 комментариев
2

Рассматривали ли вы преобразование ваших списков в хэш-наборы и использование метода Except?

Смотрите разницу между двумя списками

И: Есть ли способ получить разницу между двумя наборами объектов в С#

  • 0
    Выглядит хорошо, не могли бы вы показать мне пример, если это возможно, пожалуйста? :)
  • 1
    Согласитесь с попыткой Except (), потому что это должна быть сложность O (1) или O (log N) из-за внутреннего использования HashSet (хотя я не на 100%, но в тестировании это кажется так)
1
var items = new List<int>(oldList.Select(x => x.ItemID ));
var missingValues = newList.Where(x => !diffids.Contains(x.ItemID)).ToList();

Вы также можете использовать кроме.

  • 0
    Хм, это немного смущает меня ... Могу ли я извлечь предметы в форме класса? Не только целочисленное значение ..: D
0

Если списки достаточно велики, чтобы вложенные циклы занимали 30 секунд, я рекомендую помещать каждый элемент списка в соответствующий HashSet и использовать его для поиска исключений. Хеш-таблицы будут масштабироваться в O (1) или O (log N), тогда как сравнение 2 несортированных списков - O (n ^ 2).

Тем не менее, попробуйте использовать Linq Except()

var notinNewList = oldList.Except(newList);

Если я не ошибаюсь, внутренняя реализация .Except() опирается на HashSets

Во-вторых, если списки отсортированы или могут быть предварительно отсортированы, то вы можете выполнить линейный проход за 1 цикл без вложенного цикла, вероятно, быстрее, чем любой подход.

Я не рекомендую использовать List.Contains(), потому что это линейная реализация, которая приведет к тому же O (n ^ 2), которого вы пытаетесь избежать, хотя он выглядит просто красивее из-за синтаксического сахара Linq.

-1
var items = newList.Where(n => !oldlist.Any(o => o.ItemID == n.ItemID)).ToList();

Это более гибко, так как вам не нужно снова заходить в БД и не использовать Contains, который похож на SQL и также находится в строке.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню