Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的泛型列表比较#_C#_Linq_Generics - Fatal编程技术网

C# C语言中的泛型列表比较#

C# C语言中的泛型列表比较#,c#,linq,generics,C#,Linq,Generics,我有一个方法,可以使用字典查找两个int列表之间的差异。本质上,代码循环第一个列表,将每个int添加到字典中,并设置(在尚未出现的地方设置为1)/增加值。然后,它循环第二个列表设置(如果尚未出现,则为-1)/递减该值 一旦它循环了两个列表,您将得到一个字典,其中值=0的键表示匹配,值>=1的键表示仅在第一个列表中存在,值您可以使用泛型执行此操作: public static Dictionary<T, int> CompareLists<T>(List<T>

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


一旦它循环了两个列表,您将得到一个字典,其中值=0的键表示匹配,值>=1的键表示仅在第一个列表中存在,值您可以使用泛型执行此操作:

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;

}
公共静态字典比较列表(列表A、列表B)
{
//0匹配
//=仅1个listA
var recTable=新字典();
foreach(列表A中的T值)
{
if(recTable.ContainsKey(值))
可纠正[值]+;
其他的
recTable[值]=1;
}
foreach(列表B中的T值)
{
if(recTable.ContainsKey(值))
可纠正的[值]——;
其他的
recTable[值]=-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;
}
下面是一个实现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();
    }
}
公共类MyEq:IEqualityComparer
{
公共布尔等于(整数x,整数y)
{
返回(x%2)=(y%2);
}
公共int GetHashCode(int obj)
{
返回(对象%2)。GetHashCode();
}
}

FullOuterJoin,如下所示:

公共静态字典比较列表(列表A、列表B)
{
返回listA.FullOuterJoin(listB,
a=>a,//从列表a比较什么
b=>b,//从列表b比较什么
(a、b、键)=>
new{key=key,value=0},//如果在两者中都找到,则返回什么
new{key=key,value=-1},//如果只在
new{key=key,value=1})//如果仅在B中找到,则返回什么
.ToDictionary(a=>a.key,a=>a.value);//仅因为您需要字典
}

这是我的两分钱:

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;
}
公共静态字典比较器列表(左列表、右列表、IEqualityComparer比较器)
{
字典结果=left.ToDictionary(l=>l,l=>right.Any(r=>comparer.Equals(l,r))?0:-1);
foreach(右侧的tr.Where(T=>result.Keys.All(k=>!comparer.Equals(k,T)))
结果[r]=1;
返回结果;
}
该方法使用任何类型的
T
List
s和该类型的
T
IEqualityComparer
。然后,它首先生成包含在“left”
列表中的那些元素的字典,从而检查它们是否也在“right”
列表中,并相应地设置值

第二步添加仅包含在“right”
列表中的元素,其值为
1


这是否是一个合理的实现取决于您试图用它实现什么。我认为它很短,但仍然可读,依赖于LINQ方法的正确实现。尽管可能有更快的可能性,但如果这是针对真正大的列表或经常调用的方法,则可以考虑。

首先,这是一个合理的实现吗?
可能更适合CodeReview站点,因为它是工作代码
我想要一个可以处理任何对象的东西,调用方可以在其中定义比较逻辑
您签出了吗?(编辑:或实际上?)看看这里,如果您有相同的值在
listA
中出现两次,在
listB
中出现一次,那么它将无法正常工作,结果将是肯定的,在您的注释中显示“仅listA”。您刚刚重新创建了完整的外部联接。什么是合理的实现?如果你解释了你的功能背后的目的,人们可以提出一种更好的方法来实现它。多亏了这一点,它非常适合我想做的事情。我很难看出这比user2023861发布的解决方案更简洁/更好?很高兴接受再教育,只是看不到吗?好吧,这种方法适用于所有类型的集合、列表,它是通用的,因为它允许您确定要比较什么和保留什么。当然,在您的情况下,您只需要返回0、-1或1,但是如果您想要整个记录呢?或者你想比较一个对象列表的属性(或者多个属性)?这也是一个定义良好的已知方法(尽管实现相当新),已经存在了30年:使用FullOuterJoin,列表类型不必是相同的类型。它们也可以是完整的对象,您不必编写自定义的IEqualityComparer,只需列出要比较的对象的属性即可。它非常适合其他LINQ方法,并且可以很容易地转换为SQL(完全外部连接)。您还可以返回部分对象,或合并每个对象的一部分。它是尽可能通用的,每个人都应该从名称中了解完整外部联接的作用。感谢提供更多详细信息。与完全外部连接的概念相比,我所面临的更多的是新的实现。它的好处现在更有意义了。当然,这不适用于您增加的在一个或两个列表中多次出现同一个键的要求。
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();
    }
}
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
}
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;
}