2010-07-27 3 views
2

У меня есть 2 списка. Я хочу сравнить каждый элемент с каждым элементом для обоих списков, используя LINQ (в отличие от использования вложенного цикла). Но Содержит не отвечает моим потребностям, потому что мне нужно сделать индивидуальное сравнение. Я бы предположил, что пользовательский сопоставитель - это то, что мне нужно, но не на 100% уверен.Linq пользовательский компаратор для содержит?

Я не думаю, что это должно быть слишком сложно, но не совсем точно, что мне нужно для этого. В двух списках содержатся различные и разные типы объектов.

Update:

К сожалению, если бы я не был ясен. У меня есть 2 списка (или перечислимых) я мог бы сделать что-то вроде этого:

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

То, что я хочу сделать, это что-то вроде этого:

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

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

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

+0

Не могли бы вы объяснить ваши требования в дальнейшем, или предоставить некоторые примеры данных и ожидаемых результатов? – LukeH

+0

Переопределить GetHashCode(), чтобы разные элементы возвращали разные хэш-коды, а «те же» элементы возвращают один и тот же хэш-код. Затем будет работать так, как должно (я думаю) – PostMan

+0

@PostMan - вы никогда не должны берете на GetHashCode() возвращающие разные значения для разных элементов, только чтобы он всегда возвращал одинаковое значение для элементов, которые считаются равными. –

ответ

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) 
     ) 
    ); 
} 
+0

Спасибо. Есть ли способ сделать это более ясно? Это немного сложно читать, но, похоже, работает. –

+0

@Curtis White, Ну, вы можете сделать функцию, как я только что опубликовал. – strager

+0

Синтаксис расширения должен быть «... MultiCompare (этот IEnumerable сначала, ...' then' first.SelectMany (... ' – Jamiec

0

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

1

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

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

Смежные вопросы