首页 > 解决方案 > 创建集合的差异

问题描述

我想在 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

在这种情况下是否可以检测和耦合元素?

标签: c#diff

解决方案


正如其他人在评论中指出的那样,您可能必须改写问题以更清楚地说明所需的输出是什么。对你想要“差异合并”做什么做一些假设,我猜你需要的不仅仅是相等比较器。平等比较器只告诉你事情是否相等。我的猜测是您要比较小于等于大于

如果您必须为该方法提供自定义比较器,这是一种似是而非的实现:

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


推荐阅读