创建集合差异

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 接口,这是我的偏好。您的问题仍然不是所有事情都清楚,所以请彻底测试我的答案或更改问题。