我有一个方法可以找到两个使用字典的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项目报告正确。
想象一下,您尝试在两个文件之间协调大量付款金额的用例,重复金额完全可行,但重复哪个重复项并不重要因为报告了非调节值。
答案 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;
}
这更通用,因为:
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;
}
该方法需要List
类T
IEqualityComparer
和T
类型List
。然后它首先生成一个包含在&#34; left&#34;中的元素的字典。 List
,从而检查他们是否也在&#34;右边&#34; List
并相应地设置值。
第二步添加仅包含在&#34; right&#34;中的元素。值1
的{{1}}。
如果这是一个合理的实现取决于你想用它实现什么。我认为这是一个简短但仍然可读的,依赖于LINQ方法的正确实现。虽然可能有更快的可能性,但是如果这是针对真正的大型列表或者经常被称为方法的话,可以考虑一下。