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

C# 从同一类型的IEnumerable中选择值的唯一/不同组合,c#,.net,linq,ienumerable,C#,.net,Linq,Ienumerable,我有三个相同类型(字符串)的IEnumerable,我想从中得到唯一的值组合。不太确定如何在这里实现LINQ 通过添加-as分隔符,结果应该是这样的列表 a-p-1 b-q-4 b-r-7 c-s-8 c-s-9 d-t-10 e-u-11 数据本身处于唯一连接中。一个帐户中的所有项目都是唯一的,特定项目的所有子项目也是唯一的。您不应该以单独的顺序存储相关项目;这是一个反模式。但是,如果您的数据恰好是以这种方式提供的,您可以首先使用Zip组合序列中的项目,然后使用Distinct获得唯一值 v

我有三个相同类型(字符串)的IEnumerable,我想从中得到唯一的值组合。不太确定如何在这里实现LINQ

通过添加-as分隔符,结果应该是这样的列表

a-p-1
b-q-4
b-r-7
c-s-8
c-s-9
d-t-10
e-u-11


数据本身处于唯一连接中。一个帐户中的所有项目都是唯一的,特定项目的所有子项目也是唯一的。

您不应该以单独的顺序存储相关项目;这是一个反模式。但是,如果您的数据恰好是以这种方式提供的,您可以首先使用
Zip
组合序列中的项目,然后使用
Distinct
获得唯一值

var result = accounts.Zip(projects, (a, p) => a + "-" + p)
                     .Zip(subprojects, (a, s) => a + "-" + s)
                     .Distinct()
                     .ToList();
编辑:本着的精神,这里有一个用于压缩任意数量序列的扩展方法:

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

虽然您可以使用
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);
}

他有三个收藏品哇,没想到也是这样。谢谢我把事情弄得太复杂了。:-)如果可以的话,我会一次又一次地选择它作为答案。(因为我已经选择了它作为答案)谢谢@Douglas and Servy…这是一种非常复杂的方式。非常感谢。创建一个TriZip是正确的,但是它只限于三个IEnum。我的意思是,没有真正概括的东西,一个zip可以添加多个IEnum。另一方面,如果我多次遇到这种三重组合,使用它真的很棒+1.
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);
}
var query = accounts.TriZip(projects, subprojects,
    (account, project, subproject) => 
        new { account, project, subproject })
    .Distinct();