2013-04-02 2 views
30

У меня есть List<PropA>Найти предметы из списка, которые существуют в другом списке

PropA 
{ 
    int a; 
    int b; 
} 

и другой List<PropX>

PropX 
{ 
    int a; 
    int b; 
} 

Теперь я должен найти элементы из List<PropX>, которые существуют в List<PropA> соответствие б с использованием лямбда или LINQ.

+1

И что вы пробовали? На этот вопрос уже ответили слишком много раз ... – walther

+1

http://code.msdn.microsoft.com/LINQ-Set-Operators-374f34fe –

+0

@David Возможно, у каждого из них разные поля, которые он не показывал, или у них есть другой набор методов, хотя они имеют одинаковые значения или любое количество других причин. – Servy

ответ

29

Что вы хотите сделать, это Join две последовательности. LINQ имеет Join оператор, который делает именно то, что:

List<PropX> first; 
List<PropA> second; 

var query = from firstItem in first 
    join secondItem in second 
    on firstItem.b equals secondItem.b 
    select firstItem; 

Обратите внимание, что Join оператор в LINQ также написано, чтобы выполнить эту операцию совсем немного более эффективно, чем наивные реализаций, которые могли бы сделать линейный поиск через вторую коллекцию для каждого элемента.

+7

Существует также другой способ написания этого ... 'first.Join (второй, f => fb, s => sb, (fir, sec) => fir);' –

+0

@ MalcolmO'Hare Да и оба полностью идентичны. Это будет скомпилировано. Я обнаружил, что большинство людей предпочитают «Join», чтобы быть выписаны с использованием синтаксиса запроса по синтаксису метода, даже более того, чем любой из других методов запроса. – Servy

+0

В зависимости от того, как идет бизнес-логика и входные данные, можно включить вызов Distinct() для удаления повторяющихся значений, возвращаемых соединением. –

55
ListA.Where(a => ListX.Any(x => x.b == a.b)) 
+2

Ну, я провел простой тест, и результаты 'Join' были * существенно быстрее. http://ideone.com/xW1CnL. Вам нужно будет запустить код самостоятельно, чтобы использовать больший набор данных. – Servy

+0

Да, я забыл запустить запрос. Похоже, что при достаточно небольшом наборе данных (менее 500 элементов) стоимость экземпляра соединения перевешивает прирост производительности. –

+0

Если производительность не может быть и речи, я бы принял простоту кода. Это было бы субъективным и личным предпочтением. –

19
var commonNumbers = first.Intersect(second); 

Это даст вам общие значения между двумя списками, гораздо более быстрый и более чистый подход, затем объединение или другие выражения лямбда.

Просто попробуйте.

Источник: MSDN

+7

Это будет работать, только если 'T' был того же типа для обеих коллекций' IEnumerable ', чего нет в заданном вопросе. – Daniel

4

Ну все выше, не будет работать, если у вас есть несколько параметров, поэтому я думаю, что это лучший способ сделать это.

Например: Найти несовместимые предметы с домашних животных и домашних животных2.

var notMatchedpets = pets 
    .Where(p2 => !pets2 
    .Any(p1 => p1.Name == p2.Name && p1.age == p2.age)) 
    .ToList(); 
Смежные вопросы