我有這樣的兩名成員名單:的LINQ找到差異,兩個列表
前:彼得,肯,朱莉婭,湯姆
後:彼得·羅伯特,朱莉婭,湯姆
正如你可以看到,肯是和羅伯特是在。
我想要的是檢測到的變化。我想要列出兩個列表中發生了什麼變化。 linq如何幫助我?
我有這樣的兩名成員名單:的LINQ找到差異,兩個列表
前:彼得,肯,朱莉婭,湯姆
後:彼得·羅伯特,朱莉婭,湯姆
正如你可以看到,肯是和羅伯特是在。
我想要的是檢測到的變化。我想要列出兩個列表中發生了什麼變化。 linq如何幫助我?
您的問題沒有完全指定,但我假設您正在尋找作爲集合的差異(即排序無關緊要)。如果是這樣,你想要兩個集合中的symmetric difference。您可以使用Enumerable.Except
實現這一目標:
before.Except(after).Union(after.Except(before));
@威爾:感謝您的更正。 – jason
另一種方式:
before.Union(after).Except(before.Intersect(after))
作爲替代LINQ答案,這必須通過這兩個列表兩次,使用HashSet.SymmetricExceptWith():
var difference = new HashSet(before);
difference.SymmetricExceptWith(after);
莫非效率要高得多。
這裏是有版本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);
}
這隻適用於排序的序列,對吧?對於任意序列,不能只爲O(n)產生symdiff。 – Vlad
確實如此,只需看一下聯合迭代。它是從合併排序順序合併的稍微修改版本。雖然它對於未排序的函數不起作用,但對於排序來說它是非常有效的,所以在許多情況下,對集合進行預先排序然後使用此篩選器將更快且更易於使用內存 - > n + 2 *(n log n)而不是一些naiive所有對所有n^2或一些哈希表內存豬......當然_many_元素當然:) – quetzalcoatl
我認爲你需要定義「變」多一點。例如,是否改變了項目的順序「改變」給你? –