【问题标题】:Get an enumerable of all sub lists of an existing list获取现有列表的所有子列表的可枚举
【发布时间】:2016-03-31 10:00:30
【问题描述】:

我有一个List<T>,我想获取所有可能的子列表,例如:

[A, B, C, D, E] => [[A], [A, B], [A, B, C], [A, B, C, D], [A, B, C, D, E]]

有没有一种简单的方法可以通过 LINQ to Objects 获得这个新的可枚举对象?

编辑 1: 请注意,我只想要“前缀列表”,而不是所有可能的排列(即,显示的示例结果已经完成)。

编辑 2: 请注意,我也想保持元素的顺序。

编辑 3: 有没有办法在 O(n) 而不是 O(n²) 中获得可枚举,即通过只迭代源一次而不是多次迭代并返回某种数据上的 view每次都有一个新列表?

【问题讨论】:

  • 有一篇关于permutations by Eric Lippert的不错的博客
  • 我的问题似乎与排列无关,例如,我对 [B, A] 不感兴趣?
  • @Yuval Izzchakov:请重新打开我的问题,这不是重复的,谢谢。
  • 您需要保持排列中对象的顺序吗?因为除非你这样做,否则[A,B][B,A] 有何不同?
  • 我认为 OP 需要他展示的输出,他不需要所有可能的组合

标签: c# linq linq-to-objects


【解决方案1】:

一个很幼稚的扩展方法:

public static class Extensions
{
    public static IEnumerable<IEnumerable<T>> GetOrderedSubEnumerables<T>(
                                              this IEnumerable<T> collection)
    {
        var builder = new List<T>();
        foreach (var element in collection)
        {
            builder.Add(element);
            yield return builder;
        }
    }
}

用途:

void Main()
{
    var list = new List<string> { "A", "B", "C", "D", "E" };
    Console.WriteLine(list.GetOrderedSubEnumerables());
}

结果:

请注意,这将在您迭代集合时返回您的数据视图。但最终,如果您需要单独使用每个排列,则需要在返回之前复制每个 List&lt;T&gt;。在这种情况下,应该这样做:

public static class Extensions
{
    public static IEnumerable<IEnumerable<T>> GetOrderedSubEnumerables<T>(
                                              this IEnumerable<T> collection)
    {
        var builder = new List<T>();
        foreach (var element in collection)
        {
            builder.Add(element);
            var local = new List<T>(builder);
            yield return local;
        }
    }
}

【讨论】:

  • 我喜欢你的解决方案 :) +1
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ 谢谢:)
  • yield return 会导致创建一个新的 IEnumerable?
  • 不,他只是在每次迭代时接收数据视图。正如我在回答中添加的那样,如果他想为每个排列创建一个单独的枚举器,他将不得不返回一个新的 List&lt;T&gt;,或者让返回每个项目。
  • 所以相同的字符串实例被一次又一次地使用对吧?
【解决方案2】:

是的,您是对的,您的要求是排列的一小部分,与排列无关。所以我的建议是:

var result = Enumerable.Range(1, list.Count).
                Select(i => list.Take(i).ToList()).
                ToList();

【讨论】:

    【解决方案3】:

    您可以遍历列表中的项目数量范围并选择子列表,如下所示:

    var list = new List<string> { "A", "B", "C", "D", "E"};
    
    var query =
        from i in Enumerable.Range(1, list.Count)
        select list.Take(i);
    

    请记住,如果您的数据不在 List&lt;T&gt; Count 中,可能会很昂贵。另请注意,这会多次迭代您的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多