包含Linq自定义比较器?

时间:2010-07-27 22:10:19

标签: linq linq-to-sql

我有2个清单。我想使用LINQ将每个元素与两个列表的每个元素进行比较(而不是使用嵌套循环)。但是,Contains不能满足我的需求,因为我需要进行自定义比较。我认为自定义比较器是我需要的,但不是100%肯定。

我不认为这应该太难,但不确定我需要的工具。 2个列表都包含不同类型的对象。

更新

对不起,如果我不清楚的话。我有2个列表(或枚举)我可以做这样的事情:

foreach(item i in list1)
  foreach(otherItemType in List2)
  {
    if ( CompareItem(x) ) do something;
  }

我想做的是这样的事情:

var matches = myList1.Where(t => myList2.Something(t) ) 

Where Something是自定义比较器,也许我可以覆盖equals比较?我可以使用.Contains,但我需要做自己的逻辑进行比较。

更新: 我想过使用IEqualityComparer,但是它设置为采用T,T和T,Y的类型。我可以使用一些通用约束来解决这个问题。我觉得这应该简单/简单。

4 个答案:

答案 0 :(得分:2)

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 :(得分: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));
}

答案 2 :(得分: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表达式,但它们通常看起来有点混乱......

答案 3 :(得分:0)

我有一段时间的问题here可能会帮助你开始。