Linq пользовательский компаратор для содержит? - PullRequest
2 голосов
/ 28 июля 2010

У меня есть 2 списка.Я хочу сравнить каждый элемент с каждым элементом для обоих списков, используя LINQ (вместо использования, скажем, вложенного цикла).Но Содержимое не отвечает моим потребностям, потому что мне нужно сделать пользовательское сравнение.Я думаю, что мне нужен пользовательский компаратор, но я не уверен на 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) ) 

Где Something это пользовательский компаратор,возможно я могу переопределить сравнение равных?Я мог бы использовать .Contains, но мне нужно сделать свою собственную логику для сравнения.

Обновление: я думал об использовании IEqualityComparer, но он настроен на использование типов T, T и T, Y.Могут быть некоторые общие ограничения, которые я мог бы использовать для решения этой проблемы.Я чувствовал, что это должно быть легко / просто.

Ответы [ 4 ]

2 голосов
/ 30 июля 2010
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 голос
/ 01 августа 2010

Как насчет использования 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, хотя вы можете в равной степени использовать лямбда-выражения, они обычно выглядят немного грязно ...

1 голос
/ 01 августа 2010

Если я правильно понимаю ваш вопрос, образец ниже сделает это.Поскольку Любой принимает делегата, вы можете определить произвольное сравнение совпадений между двумя элементами списка.Если вам нужно сопоставить все элементы, используйте Все вместо Любой .

[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));
}
0 голосов
/ 28 июля 2010

У меня был вопрос здесь некоторое время назад, который может помочь вам начать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...