【问题标题】:How to combine multiple lists of same or different lengths in Linq?如何在 Linq 中组合多个相同或不同长度的列表?
【发布时间】:2013-10-22 15:33:46
【问题描述】:

我想构建一个方法或扩展方法接受多个列表并按以下方式组合它们:

假设我有两个列表:

        int[] list1 =  {3, 1, 2};
        int[] list2 =  {5, 4 };

我希望得到一个数组列表,结果如下:

[1,4]
[1,5]
[2,4]
[2,5]
[3,4]
[3,5]

我的结果数组列表中的列数将由数量决定 的列表通过并且两列都需要排序。 行数就是(列表A的长度)*(列表B的长度)*(列表N的长度)

在此示例中为 3 * 2 = 6 行。 2 列(因为有 2 个输入列表)。

用 linq 做这件事的优雅方式是什么?

谢谢!

【问题讨论】:

  • 你有没有试过先用普通循环和自然算法来解决这个问题?对于如此复杂的问题,我永远不会使用LINQ。即使LINQ 可以为您做到这一点,它也会比普通循环效率更低,hard-to-understand 更多。 不应不惜一切代价使用LINQ
  • 我同意 LINQ 有时可能更难理解且效率更低,但我想了解更多有关它的信息。我想过用普通循环解决这个问题,但对 LINQ 方式很好奇。我的应用程序不会处理大量列表,所以我认为性能应该不是问题。
  • @KingKing:这是一个用 LINQ 解决的完全合理的问题,而且一点也不复杂。二元笛卡尔积实际上是基础 LINQ 序列运算SelectMany。所有 LINQ 运算符都可以由SelectMany 构建;它是序列单子的绑定操作。 n 元笛卡尔积当然要复杂一些。
  • @EricLippert 谢谢,也许你对LINQ 太熟悉了,对我来说,有时我仍然觉得用传统循环(和单独的方法)想出解决方案比使用LINQ 更容易,但是我仍然尽可能部分地使用LINQ(不是one-line LINQ)。
  • @EricLippert 如果您像您一样发布我的回答,我将很乐意接受您的回答。当功劳归于你时,我不想接受我自己的答案。谢谢!

标签: c# .net linq list join


【解决方案1】:

尝试交叉连接

int[] list1 =  {3, 1, 2};
int[] list2 =  {5, 4 }; 

var result = (from l1 in list1
             from l2 in list2
             select new [] {l1, l2}).ToList()

【讨论】:

  • 我怎样才能把它改造成一个可以接受 n 个列表的方法?
【解决方案2】:

使用SelectMany:

var combinations = list1.SelectMany(i1 => list2.Select(i2 => new[] { i1, i2 }));

或者如果你喜欢

var combinations = list1.SelectMany(i1 => list2, (i1, i2) => new[] { i1, i2 });

如果您想按特定顺序获取结果,您可以使用OrderBy 等跟进。

【讨论】:

  • 但是如果我发送超过 2 个列表怎么办?我想有一个可以接受 n 个列表的方法。
  • @AdolfoPerez:那会更复杂。见stackoverflow.com/questions/4073713/…
  • 这正是我所需要的。
【解决方案3】:

感谢@Jon 为我指出正确的来源和@EricLippert 的聪明解决方案:

    public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
    {
        IEnumerable<IEnumerable<T>> emptyProduct =
          new[] { Enumerable.Empty<T>() };
        return sequences.Aggregate(
          emptyProduct,
          (accumulator, sequence) =>
            from accseq in accumulator
            from item in sequence
            select accseq.Concat(new[] { item }));
    }

http://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/

适用于整数和字符串:

        string[] list1 =  {"1", "2", "3"};
        string[] list2 =  { "4","5" };

        var lists = new List<string[]>(){list1,list2};

        var result = lists.CartesianProduct();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    • 2019-10-16
    • 1970-01-01
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多