I have two list of members like this:
我有两个这样的成员列表:
Before: Peter, Ken, Julia, Tom
之前:彼得,肯,朱莉娅,汤姆
After: Peter, Robert, Julia, Tom
之后:彼得,罗伯特,朱莉娅,汤姆
As you can see, Ken is is out and Robert is in.
正如你所看到的,肯已经出局了,罗伯特也在。
What I want is to detect the changes. I want a list of what has changed in both lists. How can linq help me?
我想要的是检测变化。我想要列出两个列表中已更改的内容。 linq怎么能帮助我?
4 个解决方案
#1
28
Your question is not completely specified but I assume that you are looking for the differences as sets (that is, ordering does not matter). If so, you want the symmetric difference of the two sets. You can achieve this using Enumerable.Except
:
你的问题没有完全确定,但我认为你正在寻找差异作为集合(也就是说,排序无关紧要)。如果是这样,您需要两组的对称差异。您可以使用Enumerable实现此目的。除外:
before.Except(after).Union(after.Except(before));
#2
20
As an alternative to linq answers, which have to pass both lists twice, use HashSet.SymmetricExceptWith():
作为linq答案的替代方法,必须两次传递两个列表,使用HashSet.SymmetricExceptWith():
var difference = new HashSet(before);
difference.SymmetricExceptWith(after);
Could be considerably more efficient.
可能会更有效率。
#3
5
Another way:
其他方式:
before.Union(after).Except(before.Intersect(after))
#4
2
Here is the version having O(n) complexity, provided your sequences are both ordered:
这是具有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);
}
#1
28
Your question is not completely specified but I assume that you are looking for the differences as sets (that is, ordering does not matter). If so, you want the symmetric difference of the two sets. You can achieve this using Enumerable.Except
:
你的问题没有完全确定,但我认为你正在寻找差异作为集合(也就是说,排序无关紧要)。如果是这样,您需要两组的对称差异。您可以使用Enumerable实现此目的。除外:
before.Except(after).Union(after.Except(before));
#2
20
As an alternative to linq answers, which have to pass both lists twice, use HashSet.SymmetricExceptWith():
作为linq答案的替代方法,必须两次传递两个列表,使用HashSet.SymmetricExceptWith():
var difference = new HashSet(before);
difference.SymmetricExceptWith(after);
Could be considerably more efficient.
可能会更有效率。
#3
5
Another way:
其他方式:
before.Union(after).Except(before.Intersect(after))
#4
2
Here is the version having O(n) complexity, provided your sequences are both ordered:
这是具有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);
}