.Net - 使用LINQ以特殊方式聚合树列表

时间:2011-09-18 18:43:56

标签: c# .net linq

我有树的字符串列表(列表的数量可以变化)

list1的
一个

list2中
NUM1
NUM2
NUM3

项目list3
TT

结果我想要这个字符串的列表:
A num1 TT
A num2 TT
一个数字3 TT B num1 TT
B num2 TT
B num3 TT

因此,您可以看到我想从一个列表中加入每个字符串,其中包含来自其他字符串的每个字符串。

我如何使用Linq在.Net中实现这一目标?有办法吗?

3 个答案:

答案 0 :(得分:3)

这是一个解决方案:

IEnumerable<string> MultiConcat(params IEnumerable<string>[] lists)
{
    if (lists == null) {
        return null;
    }

    if (lists.Length == 0) {
        return Enumerable.Empty<string>();
    }

    return lists.Aggregate(new[] { string.Empty } as IEnumerable<string>,
                   (acc, list) => acc.SelectMany(s1 => list.Select(s2 => s1 + s2)));
}

如何使用

var list1 = new List<string> { "A", "B" };
var list2 = new List<string> { "1", "2", "3" };
var list3 = new List<string> { "FOO", "BAR" };

foreach (var s in MultiConcat(list1, list2, list3)) {
    Console.Out.WriteLine(s);
}

<强> See it in action

工作原理

基本上这只是对Enumerable.Aggregate的一次调用。我们的想法是,我们有一个可枚举的字符串集合(“当前”)和另一个我们想要加入的字符串(“传入”)。我们

current.SelectMany(s1 => incoming.Select(s2 => s1 + s2))

这直接相当于

from var s1 in current
from var s2 in incoming
select s1 + s2

换句话说,它产生两个枚举的内连接。

Aggregate的美妙之处在于它允许我们多次执行此操作,一次处理多个“传入”集合。

答案 1 :(得分:1)

您可以声明如下的扩展程序:

static class Extensions
{
    public static IEnumerable<T> Merge<T, F, S>(this IEnumerable<F> source, IEnumerable<S> second, Func<F, S, T> func)
    {
        foreach (var item in source)
        {
            foreach (var item2 in second)
            {
                yield return func(item, item2);
            }
        }
    }
}

然后使用它:

    var res = list1
              .Merge(list2, (f,s) => f + " " + s)
              .Merge(list3, (f,s) => f + " " + s);

答案 2 :(得分:0)

from l1 in list1
from l2 in list2
from l3 in list3
select l1 + " " + l2 + " " + l3