Linq 自定义比较器包含?

问题描述 投票:0回答:4

我有 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
类型。我可能可以使用一些通用约束来解决这个问题。我觉得这应该很容易/简单。

c# linq linq-to-sql
4个回答
3
投票
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)
        )
    );
}

1
投票

如果我正确理解你的问题,下面的示例就可以做到。 由于 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));
}

1
投票

使用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 表达式,但它们通常看起来有点混乱......


0
投票

我不久前在这里有问题,可能会帮助您开始。

© www.soinside.com 2019 - 2024. All rights reserved.