1

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

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

List<Device> allDevices;

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

提前致谢。

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

List<string> commonInterfaces = allDevices.Select(device => device.Interfaces)
   .Cast<IEnumerable<string>>()
   .Aggregate(Enumerable.Intersect)
   .ToList();
4

3 回答 3

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;
}

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;
}

现在用法很简单(比较器可以用于自定义类型):

var allInterfaces = allDevices.Select(d => d.Interfaces);
var commonInterfaces = allInterfaces.CommonSubset();
Console.Write(string.Join(",", commonInterfaces));
于 2013-08-28T13:14:27.140 回答
4
var allInterfaces = from device in allDevices
                    from interface in device.Interfaces
                    select interface;

var allInterfaces = allDevices.SelectMany(device => device.Interfaces);

如果理查德道尔顿是正确的

var allCommonInterfaces = allDevices
              .Select(device => device.Interfaces.AsEnumerable())
              .Aggregate(Enumerable.Intersect);

为了好玩……这是一个更“最佳”的解决方案。

public static IEnumerable<T> CommonSubset<T>
          (this IEnumerable<IEnumerable<T>> sequences, 
           EqualityComparer<T> comparer = null)
{
    if (sequences == null) throw new ArgumentNullException("sequences");


    Enumerator<T> enumerator = sequences.GetEnumerator();
    if(enumerator.GetNext() == false)
        throw new ArgumentException("Sequences must not be empty", "sequences");


    IEnumerable<T> first = enumerator.Current;
    HashSet<T> commonSubset = new HashSet<T>(first);
    while(enumerator.GetNext())
    {
        var nextSequence = enumerator.Current;
        var toRemove = commonSubset.Except(nextSequence, comparer ?? EqualityComparer<T>.Default).ToList();
        foreach(var r in toRemove)
            commonSubset.Remove(r);
    }
    return commonSubset;
}
于 2013-08-28T13:15:11.873 回答
2

我猜你正在寻找:

List<string> allInterfaces = allDevices.SelectMany(r=> r.Interfaces).ToList();

或者您可以选择IEnumerable<string>

var allInterfaces =  allDevices.SelectMany(r=> r.Interfaces);
于 2013-08-28T13:15:11.007 回答