在捕获索引时使用 LINQ 展平列表
Posted
技术标签:
【中文标题】在捕获索引时使用 LINQ 展平列表【英文标题】:Using LINQ to flatten lists while capturing the index 【发布时间】:2012-01-19 16:29:46 【问题描述】:我有一个List<List<List<Foo>>>
,我想将其展平为List<new Foo, Ndx>
,其中Ndx 是最外层列表的索引。例如,如果我有类似的东西:
new List()
new List()
new List() new Foo("a"), new Foo("b"),
new List() new Foo("c"),
new List()
new List() new Foo("x"), new Foo("y")
对于“a”、“b”和“c”,我的 Ndx 可能最终为 0,而“x”和“y”的 Ndx 为 1。有人有 LINQ 解决方案吗?
【问题讨论】:
"我有一个 List>>" ...哇,肯定有更好的结构吗? @Yuck:Yuck 只是你的名字还是你的意见? :) @StuartGolodetz 这实际上是我的名字;我的父母很残忍。 并不意味着粗鲁地顺便说一句 - 只是因为您对数据结构表示厌恶并用“- Yuck”跟进这一事实而感到震惊:) 最终结果集中应该有多少项? 【参考方案1】:有点繁琐,但你可以这样做:
IEnumerable<Tuple<Foo,int>> result =
tree.SelectMany(
(L1,i) => L1.SelectMany(
L2 => L2.Select(
k => Tuple.Create(k,i)
)
)
);
一个可编译的版本是:
using System;
using System.Collections.Generic;
using System.Linq;
class Foo
public string s;
public Foo(string s)
this.s = s;
class Program
static void Main(string[] args)
var tree = new List<List<List<Foo>>>
new List<List<Foo>>
new List<Foo> new Foo("a"), new Foo("b") ,
new List<Foo> new Foo("c")
,
new List<List<Foo>>
new List<Foo> new Foo("x"), new Foo("y")
;
IEnumerable<Tuple<Foo,int>> result = tree.SelectMany((L1,i) => L1.SelectMany(L2 => L2.Select(k => Tuple.Create(k,i))));
foreach(var si in result)
Console.WriteLine(si.Item1.s + ' ' + si.Item2);
编辑:正如@sll 指出的那样,由于使用了Tuple
,此解决方案需要.NET 4。如有必要,适应也不会太难。
【讨论】:
@sll:很公平。我承认我一直是一名 C++ 程序员(我今年早些时候才开始使用 C#),所以我对最新的 .NET 中的新内容或新内容有些迷茫。【参考方案2】:应该这样做:
var l = new List<List<List<Foo>>>()
new List<List<Foo>>()
new List<Foo>() new Foo("a"), new Foo("b"),
new List<Foo>() new Foo("c"),
new List<List<Foo>>()
new List<Foo>() new Foo("x"), new Foo("y");
var q = l.SelectMany ((x, i) =>
x.SelectMany (y =>
y.Select (z => new z, i )));
【讨论】:
以上是关于在捕获索引时使用 LINQ 展平列表的主要内容,如果未能解决你的问题,请参考以下文章