我有三个相同类型的IEnumebles(字符串),我希望从中获得唯一的值组合。不太清楚如何在这里实现LINQ。
通过添加 - 作为分隔符
,结果应该是这样的列表 A-P-1
B-Q-4
B-R-7
C-S-8
C-S-9
d-T-10
电子的u-11
数据本身具有独特的联系。一个帐户中的所有项目都是唯一的,特定项目的所有子项目也是如此。
答案 0 :(得分:5)
您不应该将相关项目存储在单独的序列中;这是一个反模式。但是,如果这恰好是您的数据可用的方式,您可以先使用Zip
合并序列中的项目,然后使用Distinct
获取唯一值。
var result = accounts.Zip(projects, (a, p) => a + "-" + p)
.Zip(subprojects, (a, s) => a + "-" + s)
.Distinct()
.ToList();
修改:本着Servy's answer的精神,这是一个用于压缩任意数量序列的扩展方法:
public static partial class EnumerableExtensions
{
public static IEnumerable<TResult> Zip<TSource, TResult>(
this IEnumerable<IEnumerable<TSource>> sequences,
Func<IEnumerable<TSource>, TResult> resultSelector)
{
var enumerators = sequences.Select(sequence => sequence.GetEnumerator()).ToArray();
while (enumerators.All(enumerator => enumerator.MoveNext()))
yield return resultSelector(enumerators.Select(enumerator => enumerator.Current));
}
}
这就是它的消费方式:
string[][] sequences = { accounts, projects, subprojects };
var results = sequences.Zip(items => string.Join("-", items))
.Distinct()
.ToList();
答案 1 :(得分:3)
虽然您可以使用Zip
两次来压缩三个序列,但创建一个新的三向拉链很容易,并且更容易使用:
public static IEnumerable<TResult> TriZip<TSource, TResult>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
IEnumerable<TSource> third,
Func<TSource, TSource, TSource, TResult> resultSelector)
{
using (var firstIterator = first.GetEnumerator())
using (var secondIterator = second.GetEnumerator())
using (var thirdIterator = third.GetEnumerator())
while (firstIterator.MoveNext() &&
secondIterator.MoveNext() &&
thirdIterator.MoveNext())
yield return resultSelector(firstIterator.Current,
secondIterator.Current,
thirdIterator.Current);
}
现在你的工作就是调用这个方法,加上Distinct
:
var query = accounts.TriZip(projects, subprojects,
(account, project, subproject) =>
new { account, project, subproject })
.Distinct();