我有一个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 而不是每次新的清单?
答案 0 :(得分:4)
一种非常天真的扩展方法:
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<T>
,然后再将其放回。在这种情况下,应该这样做:
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 :(得分:0)
是的,你是对的,你的要求是排列的一小部分,与排列无关。所以我的建议在这里:
var result = Enumerable.Range(1, list.Count).
Select(i => list.Take(i).ToList()).
ToList();
答案 2 :(得分:0)
您可以迭代列表中一定数量的项目,并选择子列表,如下所示:
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<T>
Count
,可能会很昂贵。另请注意,这会多次迭代您的数据。