Есть ли встроенный способ выполнить пересечение в списке списков с использованием LINQ?

#c# #linq

#c# #linq

Вопрос:

Допустим, у меня есть

 { { "a", "b", "c" }, { "d", "b", "c" }, { "z", "a", "c" } }
 

Я могу перебирать внешний список и выполнять пересечение в каждом внутреннем списке и получать:

 { "a", "b", "c", "d", "z" }
 

Тем не менее, мне интересно, есть ли что-то встроенное.NET для этого. Я чувствую, что должен быть способ сделать что-то вроде:

 listOfLists.Intersect();
 

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

В итоге я перегружал его для своих собственных целей, но мне интересно, не нужно ли мне было.

     internal static string Intersect(this IEnumerable<string> inputs)
    {
        var temp = inputs.FirstOrDefault().ToCharArray();
        foreach (var item in inputs.Skip(1))
        {
            temp = temp.Intersect(item).ToArray();
        }
        return new string(temp);
    }
 

Комментарии:

1. Ваш пример неверен — вы должны получать только c в том случае, если вы выполняете пересечение. Вы имели в виду объединение вместо этого? Что вы пытаетесь найти здесь, общие буквы, уникальные буквы? Обратите внимание, что это будет надежно работать только с текстом ASCII.

Ответ №1:

Вы можете использовать оператор Aggregate LINQ.

 internal static string Intersect(this IEnumerable<string> inputs) =>
    string.Join("", inputs.Select(x => x.AsEnumerable()).Aggregate((x, y) => x.Union(y)));
 

Обратите внимание, что ожидаемый результат, который вы показали, — это a Union из всех букв в трех строках, а не an Intersect . Но если вы на самом деле имели в виду пересечение, просто используйте x.Intersect(y) .

Комментарии:

1. Даст ли это лучшую производительность, чем. SelectMany(l => l, (список, элемент) => элемент). Distinct() ?

2. Да, когда я изначально писал вопрос, я спрашивал о пересечении объединения except и concat . Я очистил его только до одного в целях ясности, но не оставил правильный пример. Спасибо.