C#

时间:2015-12-08 16:39:32

标签: c# linq generics

我有一个方法可以找到两个使用字典的int列表之间的差异。本质上,代码循环第一个列表,将每个int添加到字典中并设置(到1还没有存在)/递增值。然后它循环第二个列表设置(到-1还没有出现)/递减值。

一旦它循环了两个列表,你最终会得到一个字典,其中值为0的键表示匹配,值为> = 1的键表示仅存在于第一个列表中,值< = - 1表示仅存在于第二个清单。

首先,这是一个明智的实施吗?

其次,我想让它更通用,目前它只能处理基于int的列表。我喜欢可以处理调用者可能定义比较逻辑的任何对象的东西......

    public static Dictionary<int, int> CompareLists(List<int> listA, List<int> listB)
    {
        // 0        Match
        // <= -1    listB only
        // >= 1     listA only
        var recTable = new Dictionary<int, int>();

        foreach (int value in listA)
        {
            if (recTable.ContainsKey(value))
                recTable[value]++;
            else
                recTable[value] = 1;
        }

        foreach (int value in listB)
        {
            if (recTable.ContainsKey(value))
                recTable[value]--;
            else
                recTable[value] = -1;
        }

        return recTable;

    }

提前致谢!

回复: &#34;如果你有相同的值在listA中出现两次而在listB中出现两次,那么它将无法正常工作,结果将为正数,即&#34; listA only&#34;在你的评论中。&#34;

让我澄清一下;如果一个值在listA中出现两次,它也应该在listB中出现两次 - 所以如果一个值在listA中两次而在listB中一次,我不关心listA中哪一个选择匹配,只要一个非-reconciling项目报告正确。

想象一下,您尝试在两个文件之间协调大量付款金额的用例,重复金额完全可行,但重复哪个重复项并不重要因为报告了非调节值。

4 个答案:

答案 0 :(得分:1)

要回答你的第二个问题,这里是如何使它更通用:

public static Dictionary<T, int> CompareLists<T>(IEnumerable<T> listA, 
    IEnumerable<T> listB, IEqualityComparer<T> comp)
{
    var recTable = new Dictionary<T, int>(comp);

    foreach (var value in listA)
    {
        if (recTable.ContainsKey(value))
            recTable[value]++;
        else
            recTable[value] = 1;
    }

    foreach (var value in listB)
    {
        if (recTable.ContainsKey(value))
            recTable[value]--;
        else
            recTable[value] = -1;
    }

    return recTable;
}

这更通用,因为:

  • 我传入的是T型而不是int。
  • 我使用IEnumerables而不是Lists。
  • 我传入IEqualityComparer并将其传递给需要使用它的Dictionary构造函数。
  • 我在foreach循环中使用var而不是int。您也可以使用T

您可以这样调用此代码:

static void Main()
{
    int[] arr1 = { 1, 2, 3 };
    int[] arr2 = { 3, 2, 1 };

    var obj = CompareLists(arr1, arr2, EqualityComparer<int>.Default);

    Console.ReadLine();
}

以下是实现IEqualityComparer的示例。这会将所有奇数整数视为相等且所有偶数均等于:

public class MyEq : IEqualityComparer<int>
{
    public bool Equals(int x, int y)
    {
        return (x % 2) == (y % 2);
    }

    public int GetHashCode(int obj)
    {
        return (obj % 2).GetHashCode();
    }
}

答案 1 :(得分:1)

在这里找到FullOuterJoin:LINQ - Full Outer Join

public static Dictionary<int, int> CompareLists(List<int> listA, List<int> listB)
{
  return listA.FullOuterJoin(listB,
    a=>a, // What to compare from ListA
    b=>b, // What to compare from ListB
    (a,b,key)=>
      new {key=key,value=0}, // What to return if found in both
      new {key=key,value=-1},// What to return if found only in A
      new {key=key,value=1}) // What to return if found only in B
    .ToDictionary(a=>a.key,a=>a.value); // Only because you want a dictionary
}

答案 2 :(得分:0)

您可以使用Generics执行此操作:

public static Dictionary<T, int> CompareLists<T>(List<T> listA, List<T> listB)
{
    // 0        Match
    // <= -1    listB only
    // >= 1     listA only
    var recTable = new Dictionary<T, int>();

    foreach (T value in listA)
    {
        if (recTable.ContainsKey(value))
            recTable[value]++;
        else
            recTable[value] = 1;
    }

    foreach (T value in listB)
    {
        if (recTable.ContainsKey(value))
            recTable[value]--;
        else
            recTable[value] = -1;
    }

    return recTable;

}

答案 3 :(得分:0)

这是我的两分钱:

public static Dictionary<T, int> CompareLists<T>(List<T> left, List<T> right, IEqualityComparer<T> comparer)
{
    Dictionary<T, int> result = left.ToDictionary(l => l, l => right.Any(r => comparer.Equals(l, r)) ? 0 : -1);
    foreach (T r in right.Where(t => result.Keys.All(k => !comparer.Equals(k, t))))
        result[r] = 1;
    return result;
}

该方法需要ListT IEqualityComparerT类型List。然后它首先生成一个包含在&#34; left&#34;中的元素的字典。 List,从而检查他们是否也在&#34;右边&#34; List并相应地设置值。

第二步添加仅包含在&#34; right&#34;中的元素。值1的{​​{1}}。

如果这是一个合理的实现取决于你想用它实现什么。我认为这是一个简短但仍然可读的,依赖于LINQ方法的正确实现。虽然可能有更快的可能性,但是如果这是针对真正的大型列表或者经常被称为方法的话,可以考虑一下。