так что в основном у меня есть два больших списка, например:
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"...
отредактированный
Кроме будет работать намного быстрее. Здесь вы можете прочитать о его исполнении
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()
Рассматривали ли вы преобразование ваших списков в хэш-наборы и использование метода Except?
Смотрите разницу между двумя списками
И: Есть ли способ получить разницу между двумя наборами объектов в С#
var items = new List<int>(oldList.Select(x => x.ItemID ));
var missingValues = newList.Where(x => !diffids.Contains(x.ItemID)).ToList();
Вы также можете использовать кроме.
Если списки достаточно велики, чтобы вложенные циклы занимали 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.
var items = newList.Where(n => !oldlist.Any(o => o.ItemID == n.ItemID)).ToList();
Это более гибко, так как вам не нужно снова заходить в БД и не использовать Contains, который похож на SQL и также находится в строке.
intersection
иunion
LINQ
docs.microsoft.com/en-us/dotnet/api/…