我将从我的数据结构开始。
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();
答案 0 :(得分: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;
}
如果您想重复使用它,可以将其作为扩展方法:
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));
答案 1 :(得分: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;
}
答案 2 :(得分:2)
我猜你在找:
List<string> allInterfaces = allDevices.SelectMany(r=> r.Interfaces).ToList();
或者您可以选择IEnumerable<string>
之类的:
var allInterfaces = allDevices.SelectMany(r=> r.Interfaces);