创建集合差异
Create diff of collections
我想在 C# (LINQ) 中创建两个集合的“合并差异”。假设,以下 2 个字符串集合,并且输入集合已排序:
a - a
b - c
e - d
预期的输出应该是:
a - a
b - null
null - c
null - d
e - null
现在,我有以下实现:
public static IEnumerable<KeyValuePair<T, T>> Diff<T>(IEnumerable<T> a, IEnumerable<T> b, IEqualityComparer<T> comparer)
{
List<T> listA = a.ToList();
List<T> listB = b.ToList();
int indexA = 0;
int indexB = 0;
while (indexA < listA.Count || indexB < listB.Count)
{
if (indexA == listA.Count && indexB < listB.Count)
{
yield return new KeyValuePair<T, T>(default(T), listB[indexB++]);
}
else if (indexA < listA.Count && indexB == listB.Count)
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
else if (comparer.Equals(listA[indexA], listB[indexB]))
{
yield return new KeyValuePair<T, T>(listA[indexA++], listB[indexB++]);
}
else
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
}
}
产生以下输出:
a - a
b - null
e - null
null - c
null - d
任何人都可以帮助我,如何修复它(是否有开箱即用的 nuget 包?)
更新:
感谢@Daniel 的回答,如果集合不包含重复记录,它会起作用。
在这种情况下,不能选择过滤重复项目或保证没有重复项。
我面临的下一个问题是:
假设我有两个集合(字符串列表):
Collection A: Collection B:
Apple Apple
Apple Peach
Peach
实际结果如下:
Result Collection
Apple - Apple
null - Peach
Apple - null
Peach - null
以及我的期望:
Result Collection
Apple - Apple
Apple - null
Peach - Peach
在这种情况下是否可以检测和耦合元素?
正如其他人在评论中指出的那样,您可能需要改写问题以更清楚地说明所需的输出是什么。对您希望“差异合并”执行的操作做出一些假设,我的猜测是您需要的不仅仅是相等比较器。相等比较器只会告诉您事物是否 相等 。我的猜测是您想比较 小于 、 等于 和 大于 。
如果您必须为该方法提供自定义比较器,这是一种可能的实现方式:
public static IEnumerable<KeyValuePair<T, T>> Diff<T>(IEnumerable<T> a, IEnumerable<T> b, IComparer<T> comparer)
{
List<T> listA = a.ToList();
List<T> listB = b.ToList();
int indexA = 0;
int indexB = 0;
while (indexA < listA.Count || indexB < listB.Count)
{
if (indexA == listA.Count && indexB < listB.Count)
{
yield return new KeyValuePair<T, T>(default(T), listB[indexB++]);
}
else if (indexA < listA.Count && indexB == listB.Count)
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
else
{
int comparison = comparer.Compare(listA[indexA], listB[indexB]);
if (comparison == 0)
{
yield return new KeyValuePair<T, T>(listA[indexA++], listB[indexB++]);
}
else if (comparison < 0)
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
else
{
yield return new KeyValuePair<T, T>(default(T), listB[indexB++]);
}
}
}
}
或者您可以放弃 Comparer 参数并在 T 上添加类型约束以实现 IComparable 接口,这是我的偏好。您的问题仍然不是所有事情都清楚,所以请彻底测试我的答案或更改问题。
我想在 C# (LINQ) 中创建两个集合的“合并差异”。假设,以下 2 个字符串集合,并且输入集合已排序:
a - a
b - c
e - d
预期的输出应该是:
a - a
b - null
null - c
null - d
e - null
现在,我有以下实现:
public static IEnumerable<KeyValuePair<T, T>> Diff<T>(IEnumerable<T> a, IEnumerable<T> b, IEqualityComparer<T> comparer)
{
List<T> listA = a.ToList();
List<T> listB = b.ToList();
int indexA = 0;
int indexB = 0;
while (indexA < listA.Count || indexB < listB.Count)
{
if (indexA == listA.Count && indexB < listB.Count)
{
yield return new KeyValuePair<T, T>(default(T), listB[indexB++]);
}
else if (indexA < listA.Count && indexB == listB.Count)
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
else if (comparer.Equals(listA[indexA], listB[indexB]))
{
yield return new KeyValuePair<T, T>(listA[indexA++], listB[indexB++]);
}
else
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
}
}
产生以下输出:
a - a
b - null
e - null
null - c
null - d
任何人都可以帮助我,如何修复它(是否有开箱即用的 nuget 包?)
更新:
感谢@Daniel 的回答,如果集合不包含重复记录,它会起作用。
在这种情况下,不能选择过滤重复项目或保证没有重复项。
我面临的下一个问题是:
假设我有两个集合(字符串列表):
Collection A: Collection B:
Apple Apple
Apple Peach
Peach
实际结果如下:
Result Collection
Apple - Apple
null - Peach
Apple - null
Peach - null
以及我的期望:
Result Collection
Apple - Apple
Apple - null
Peach - Peach
在这种情况下是否可以检测和耦合元素?
正如其他人在评论中指出的那样,您可能需要改写问题以更清楚地说明所需的输出是什么。对您希望“差异合并”执行的操作做出一些假设,我的猜测是您需要的不仅仅是相等比较器。相等比较器只会告诉您事物是否 相等 。我的猜测是您想比较 小于 、 等于 和 大于 。
如果您必须为该方法提供自定义比较器,这是一种可能的实现方式:
public static IEnumerable<KeyValuePair<T, T>> Diff<T>(IEnumerable<T> a, IEnumerable<T> b, IComparer<T> comparer)
{
List<T> listA = a.ToList();
List<T> listB = b.ToList();
int indexA = 0;
int indexB = 0;
while (indexA < listA.Count || indexB < listB.Count)
{
if (indexA == listA.Count && indexB < listB.Count)
{
yield return new KeyValuePair<T, T>(default(T), listB[indexB++]);
}
else if (indexA < listA.Count && indexB == listB.Count)
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
else
{
int comparison = comparer.Compare(listA[indexA], listB[indexB]);
if (comparison == 0)
{
yield return new KeyValuePair<T, T>(listA[indexA++], listB[indexB++]);
}
else if (comparison < 0)
{
yield return new KeyValuePair<T, T>(listA[indexA++], default(T));
}
else
{
yield return new KeyValuePair<T, T>(default(T), listB[indexB++]);
}
}
}
}
或者您可以放弃 Comparer 参数并在 T 上添加类型约束以实现 IComparable 接口,这是我的偏好。您的问题仍然不是所有事情都清楚,所以请彻底测试我的答案或更改问题。