从IEnumerable中选择相同类型的唯一/不同值组合

时间:2014-01-10 17:18:21

标签: c# .net linq ienumerable

我有三个相同类型的IEnumebles(字符串),我希望从中获得唯一的值组合。不太清楚如何在这里实现LINQ。

Input data would look like this, one column represents one IEnum

通过添加 - 作为分隔符

,结果应该是这样的列表

A-P-1
B-Q-4
B-R-7
C-S-8
C-S-9
d-T-10
电子的u-11

数据本身具有独特的联系。一个帐户中的所有项目都是唯一的,特定项目的所有子项目也是如此。

2 个答案:

答案 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();