我有 2 个列表/可枚举。我想使用 LINQ(而不是使用嵌套循环)将两个列表中的每个元素与每个元素进行比较。但是,包含不能满足我的需求,因为我需要进行自定义比较。我想我需要一个自定义比较器,但不是 100% 确定。
我认为这应该不会太困难,但不确定我到底需要什么工具。这两个列表都包含不同类型的对象。
我可以做这样的事情:
foreach(item i in list1)
foreach(otherItemType in List2)
{
if ( CompareItem(x) ) do something;
}
我想做的是这样的:
var matches = myList1.Where(t => myList2.Something(t))
其中
Something
是自定义比较器。也许我可以覆盖等于比较?我可以使用 .Contains
,但我需要用自己的逻辑进行比较。
我想过使用
IEqualityComparer
但这被设置为采用 T, T
和 T, Y
类型。我可能可以使用一些通用约束来解决这个问题。我觉得这应该很容易/简单。
var matches = myList1.SelectMany(
t1 => myList2.Where(
t2 => t2.Something(t1)
)
);
内部
Where
就像内部 foreach
循环,外部 SelectMany
在迭代后连接结果,就像外部 foreach
循环一样。
您还可以创建一个函数来为您执行此操作(未经测试;无法回忆扩展语法):
public static IEnumerable<T2> MultiCompare<T1, T2>(this IEnumerable<T1> first, IEnumerable<T2> second, Func<bool, T1, T2> comparer) {
return first.SelectMany(
t1 => second.Where(
t2 => comparer(t1, t2)
)
);
}
如果我正确理解你的问题,下面的示例就可以做到。 由于 Any 接受委托,因此您可以定义列表的两个元素之间的任意匹配比较。 如果您需要匹配所有元素,请使用 All 代替 Any。
[Test]
public void StackOverflow()
{
var digits = new int[] {1, 2, 4, 9};
var strings = new string[] {"1", "4", "5", "7"};
var matches = strings.Where(s => digits.Any(d => d.ToString() == s)).ToList();
// Prints
// 1
// 4
matches.ForEach(x => System.Diagnostics.Debug.WriteLine(x));
}
使用Enumerable.Join怎么样?
var list = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<string> { "2", "4", "5" };
var matches = from i in list
join s in list2 on i.ToString() equals s
select i; // if you want to use the matching items from the 1st list
// there's no ForEach on Enumerable so you'd have to write the extension yourself (which is easy)
// or you could just output matches to a List first
matches.ToList().ForEach(i => Console.WriteLine(i));
说到连接,我强烈喜欢 linq 查询语法,尽管您同样可以使用 Lambda 表达式,但它们通常看起来有点混乱......
我不久前在这里有问题,可能会帮助您开始。