Linq обнаруживает различия в двух списках
У меня есть два списка таких элементов:
До: Питер, Кен, Джулия, Том
После: Питер, Роберт, Джулия, Том
Как вы можете видеть, Кен не работает, и Роберт находится.
Я хочу обнаружить изменения. Мне нужен список изменений в обоих списках. Как мне помочь linq?
Ответы
Ответ 1
Ваш вопрос не полностью указан, но я предполагаю, что вы ищете различия в качестве наборов (то есть упорядочение не имеет значения). Если это так, вы хотите симметричную разницу двух наборов. Вы можете достичь этого, используя Enumerable.Except
:
before.Except(after).Union(after.Except(before));
Ответ 2
В качестве альтернативы ответам linq, которые должны пройти оба списка дважды, используйте HashSet.SymmetricExceptWith():
var difference = new HashSet(before);
difference.SymmetricExceptWith(after);
Может быть значительно более эффективным.
Ответ 3
Другой способ:
before.Union(after).Except(before.Intersect(after))
Ответ 4
Вот версия, имеющая сложность O (n), если ваши последовательности упорядочены:
public static IEnumerable<T> SymmetricDifference<T>(IEnumerable<T> coll1, IEnumerable<T> coll2, IComparer<T> cmp)
{
using (IEnumerator<T> enum1 = coll1.GetEnumerator())
using (IEnumerator<T> enum2 = coll2.GetEnumerator())
{
bool enum1valid = enum1.MoveNext();
bool enum2valid = enum2.MoveNext();
while (enum1valid && enum2valid)
{
int cmpResult = cmp.Compare(enum1.Current, enum2.Current);
if (cmpResult < 0)
{
yield return enum1.Current;
enum1valid = enum1.MoveNext();
}
else if (cmpResult > 0)
{
yield return enum2.Current;
enum2valid = enum2.MoveNext();
}
else
{
enum1valid = enum1.MoveNext();
enum2valid = enum2.MoveNext();
}
}
while (enum1valid)
{
yield return enum1.Current;
enum1valid = enum1.MoveNext();
}
while (enum2valid)
{
yield return enum2.Current;
enum2valid = enum2.MoveNext();
}
}
}
public static IEnumerable<T> SymmetricDifference<T>(IEnumerable<T> coll1, IEnumerable<T> coll2)
{
return SymmetricDifference(coll1, coll2, Comparer<T>.Default);
}