Linq选择嵌套列表的公共子集

sid*_*don 1 c# linq

我将从我的数据结构开始.

class Device
{
   public List<string> Interfaces { get; set; }
}

List<Device> allDevices;
Run Code Online (Sandbox Code Playgroud)

我想使用Linq查询来选择allDevices列表中每个设备中存在的所有接口(字符串).

谢谢,谢谢.

更新:感谢Aron我设法解决了这个问题.这是我的解决方案:

List<string> commonInterfaces = allDevices.Select(device => device.Interfaces)
   .Cast<IEnumerable<string>>()
   .Aggregate(Enumerable.Intersect)
   .ToList();
Run Code Online (Sandbox Code Playgroud)

Tim*_*ter 5

您可以使用Enumerable.Intersect,例如:

IEnumerable<string> commonSubset = allDevices.First().Interfaces;
foreach (var interfaces in allDevices.Skip(1).Select(d => d.Interfaces))
{
    commonSubset = commonSubset.Intersect(interfaces);
    if (!commonSubset.Any())
        break;
}
Run Code Online (Sandbox Code Playgroud)

DEMO

如果要重用它,可以将其作为扩展方法:

public static IEnumerable<T> CommonSubset<T>(this IEnumerable<IEnumerable<T>> sequences)
{
    return CommonSubset(sequences,  EqualityComparer<T>.Default);
}

public static IEnumerable<T> CommonSubset<T>(this IEnumerable<IEnumerable<T>> sequences, EqualityComparer<T> comparer)
{
    if (sequences == null) throw new ArgumentNullException("sequences");
    if (!sequences.Any()) throw new ArgumentException("Sequences must not be empty", "sequences");

    IEnumerable<T> commonSubset = sequences.First();
    foreach (var sequence in sequences.Skip(1))
    {
        commonSubset = commonSubset.Intersect(sequence, comparer);
        if (!commonSubset.Any())
            break;
    }
    return commonSubset;
}
Run Code Online (Sandbox Code Playgroud)

现在使用非常简单(比较器可用于自定义类型):

var allInterfaces = allDevices.Select(d => d.Interfaces);
var commonInterfaces = allInterfaces.CommonSubset();
Console.Write(string.Join(",", commonInterfaces));
Run Code Online (Sandbox Code Playgroud)