简体   繁体   English

获取现有列表的所有子列表的可枚举

[英]Get an enumerable of all sub lists of an existing list

I have a List<T> and I want to obtain all possible sub lists, eg: 我有一个List<T> ,我想获得所有可能的子列表,例如:

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

Is there an easy way to do obtain this new enumerable with LINQ to Objects? 有没有一种简单的方法可以使用LINQ to Objects获取这个新的可枚举?

EDIT 1: Note that I only want "prefix lists", not all possible permutations (ie, the shown example result is already complete). 编辑1:请注意,我只需要“前缀列表”,而不是所有可能的排列(即,显示的示例结果已经完成)。

EDIT 2: Note that I want to maintain the order of the elements as well. 编辑2:请注意,我也想维护元素的顺序。

EDIT 3: Is there a way to obtain the enumerables in O(n) instead of O(n²), ie, by iterating over the source only once instead of multiple times and returning some kind of view on the data instead of a new list each time? 编辑3:有没有办法获得O(n)中的枚举而不是O(n²),即通过仅在源上迭代一次而不是多次并在数据上返回某种视图而不是新的列表每一次?

A very naive extension method: 一种非常天真的扩展方法:

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

Use: 使用:

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

Result: 结果:

排列

Note this will return views of your data as you iterate the collection. 请注意,在迭代集合时,这将返回数据的视图。 But eventually, if you need to consume each permutation separately, you'll need to copy each List<T> over before yielding it back. 但最终,如果您需要单独使用每个排列,则需要先复制每个List<T> ,然后再将其返回。 In that case, this should do it: 在这种情况下,这应该这样做:

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

Yes you are right, your requirement is such a small subset of permutations that is has nothing to do with permutations anymore. 是的,你是对的,你的要求是排列的一小部分,与排列无关。 So here my suggestion: 所以这里我的建议是:

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

You could iterate over a range of the number of items in your list and select the sublist like so: 您可以迭代列表中一定数量的项目,并选择子列表,如下所示:

var list = new List<string> { "A", "B", "C", "D", "E"};

var query =
    from i in Enumerable.Range(1, list.Count)
    select list.Take(i);

Keep in mind that if your data is not in a List<T> Count might be expensive. 请记住,如果您的数据不在List<T> Count可能很昂贵。 Also keep in mind that this iterates over your data more than once. 另请注意,这会不止一次地迭代您的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM