Разница между двумя списками
У меня есть два общих списка, заполненных таможнями.
Мне нужно получить разницу между этими двумя списками (элементы, которые находятся в первом без элементов во втором) в третьем.
Я думал, что использование .Except()
было хорошей идеей, но я не понимаю, как это использовать.
Помогите!
Ответы
Ответ 1
Использование Except
- верный путь. Если ваш тип переопределяет Equals
и GetHashCode
, или вас интересует только равенство ссылочного типа (т.е. Две ссылки "равны", только если они ссылаются на один и тот же объект), вы можете просто использовать:
var list3 = list1.Except(list2).ToList();
Если вам нужно выразить собственное представление о равенстве, например, по идентификатору, вам нужно реализовать IEqualityComparer<T>
. Например:
public class IdComparer : IEqualityComparer<CustomObject>
{
public int GetHashCode(CustomObject co)
{
if (co == null)
{
return 0;
}
return co.Id.GetHashCode();
}
public bool Equals(CustomObject x1, CustomObject x2)
{
if (object.ReferenceEquals(x1, x2))
{
return true;
}
if (object.ReferenceEquals(x1, null) ||
object.ReferenceEquals(x2, null))
{
return false;
}
return x1.Id == x2.Id;
}
}
Тогда используйте:
var list3 = list1.Except(list2, new IdComparer()).ToList();
Обратите внимание, что это удалит все дубликаты элементов. Если вам нужно сохранить дубликаты, было бы проще создать набор из list2
и использовать что-то вроде:
var list3 = list1.Where(x => !set2.Contains(x)).ToList();
Ответ 2
Вы можете сделать что-то вроде этого:
var result = customlist.Where(p => !otherlist.Any(l => p.someproperty == l.someproperty));
Ответ 3
Я думаю, что важно подчеркнуть - использование Кроме метода вернет вам элементы, которые находятся в первом, без элементов только во втором. Он не возвращает те элементы в секунду, которые не появляются в первом.
var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };
var list3 = list1.Except(list2).ToList(); //list3 contains only 1, 2
Но если вы хотите получить реальную разницу между двумя списками:
Предметы, которые находятся в первом без предметов во втором
и предметы, которые находятся во втором, без предметов в первом.
Вам нужно использовать исключение дважды:
var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };
var list3 = list1.Except(list2); //list3 contains only 1, 2
var list4 = list2.Except(list1); //list4 contains only 6, 7
var resultList = list3.Concat(list4).ToList(); //resultList contains 1, 2, 6, 7
Или вы можете использовать метод SymmetricExceptWith HashSet. Но это меняет набор, на котором вызывается:
var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };
var list1Set = list1.ToHashSet(); //.net framework 4.7.2 and .net core 2.0 and above otherwise new HashSet(list1)
list1Set.SymmetricExceptWith(list2);
var resultList = list1Set.ToList(); //resultList contains 1, 2, 6, 7
Ответ 4
var third = first.Except(second);
(вы также можете вызвать ToList()
после Except()
, если вам не нравятся ссылки на ленивые коллекции.)
Метод Except()
сравнивает значения с использованием сравнения по умолчанию, если сравниваемые значения относятся к базовым типам данных, таким как int
, string
, decimal
и т.д.
В противном случае сравнение будет производиться по адресу объекта, что, вероятно, не то, что вы хотите... В этом случае создайте свои пользовательские объекты IComparable
(или внесите пользовательский IEqualityComparer
и передайте его в Except()
).
Ответ 5
Поскольку метод расширения Except работает на двух IEumerables, мне кажется, что это будет операция O (n ^ 2). Если производительность является проблемой (если говорят, что ваши списки большие), я бы предложил создать HashSet из списка1 и использовать метод HashSet ExceptWith.
Ответ 6
бит поздно, но вот работающее решение для меня
var myBaseProperty = (typeof(BaseClass)).GetProperties();//get base code properties
var allProperty = entity.GetProperties()[0].DeclaringType.GetProperties();//get derived class property plus base code as it is derived from it
var declaredClassProperties = allProperty.Where(x => !myBaseProperty.Any(l => l.Name == x.Name)).ToList();//get the difference
В приведенном выше кодексе я получаю разницу в свойствах между моим базовым классом и списком производных классов
Ответ 7
(LINQ) (С#) В этом примере показано, как использовать LINQ для сравнения двух списков строк и вывода тех строк, которые находятся в names1.txt, но не в names2.txt, с помощью .Except().
// Create the IEnumerable data sources.
string[] names1 = System.IO.File.ReadAllLines(@"../../../names1.txt");
string[] names2 = System.IO.File.ReadAllLines(@"../../../names2.txt");
// Create the query. Note that method syntax must be used here.
IEnumerable<string> differenceQuery = names1.Except(names2);
// Execute the query.
Console.WriteLine("The following lines are in names1.txt but not names2.txt");
foreach (string s in differenceQuery)
Console.WriteLine(s);
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Ответ 8
var list3 = list1.Where(x => !list2.Any(z => z.Id == x.Id)).ToList();
Примечание. list3
будет содержать элементы или объекты, которых нет в обоих списках.
Примечание: это ToList()
не toList()
Ответ 9
var resultList = checklist.Where(p => myList.All(l => p.value != l.value)).ToList();
Ответ 10
Если оба списка реализуют интерфейс IEnumerable, вы можете достичь этого с помощью LINQ.
list3 = list1.where(i => !list2.contains(i));
Ответ 11
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
List<int> listDifference = new List<int>();
foreach (var item1 in list1)
{
foreach (var item2 in list2)
{
if (item1 != item2)
listDifference.Add(item1);
}
}
Ответ 12
List<ObjectC> _list_DF_BW_ANB = new List<ObjectC>();
List<ObjectA> _listA = new List<ObjectA>();
List<ObjectB> _listB = new List<ObjectB>();
foreach (var itemB in _listB )
{
var flat = 0;
foreach(var itemA in _listA )
{
if(itemA.ProductId==itemB.ProductId)
{
flat = 1;
break;
}
}
if (flat == 0)
{
_list_DF_BW_ANB.Add(itemB);
}
}