. net -使用LINQ以一种特殊的方式聚合树列表

本文关键字:方式聚 列表 一种 LINQ 使用 net | 更新日期: 2023-09-27 18:09:01

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

list1
一个
B

用于
num1
num2
num3

list3
TT

作为结果,我想要这个字符串的列表:


A num3 TT



正如你所看到的,我想将一个列表中的每个字符串与另一个列表中的每个字符串连接起来。

如何在。net中使用Linq实现这一点?有办法吗?

. net -使用LINQ以一种特殊的方式聚合树列表

解决方案:

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

实际操作

工作原理

基本上它只是一个对Enumerable.Aggregate的调用。这个想法是,我们有一个可枚举的字符串集合("current")和另一个我们想要连接的字符串集合("incoming")。我们做

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

直接等价于

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

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

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

你可以这样声明一个扩展:

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);
from l1 in list1
from l2 in list2
from l3 in list3
select l1 + " " + l2 + " " + l3