将c嵌套for循环转换为声明c#
如何将嵌套for循环转换为声明风格?将c嵌套for循环转换为声明c#
示例代码:
List<String> words = new List<String>();
Books.ForEach(book => book.ForEach(page =>
page.ForEach(line =>words.Add(CreateWord(book, page, line)))));
如果你想提高可读性,那么你可以接近一步一步的。首先将每个book
条目展开为一系列(书,页)对。然后每一对转换为一个三元组(书,页面,行)并使用CreateWords
方法将其转换为字符串。
代码告诉多字,这是它的外观:
List<string> words = Books
.SelectMany(book => book.Pages.Select(page => new
{
Book = book,
Page = page
}))
.SelectMany(pair => pair.Page.Lines.SelectMany(line =>
new CreateWords(book, page, line));
这可能不是最可读的一块LINQ代码。但它往往是这样的。 LINQ倾向于生成紧凑但难看的映射代码。
在相关说明中,我想知道CreateWords
方法的用途是什么?如果它只返回一串字符串,那么不需要书,页和线的整个冒险。如果我是对的,你可能会改变CreateWords
只接收表示该行的单个字符串 - 它根本不需要书或页面对象。在这种情况下,查询将被简化:
List<string> words = Books
.SelectMany(book => book.Pages)
.SelectMany(page => page.Lines)
.SelectMany(line => CreateWords(line));
你不需要匿名类型。通过在彼此内部进行选择,您可以完全访问所有选择。 – Dispersia
虽然这解释了使用匿名类型,并且可能(更好或更糟)稍微冗长一点,但Rob的原始SelectMany()调用是嵌套的,因此可以在没有包装对象的情况下引用书和页面。我可能会选择更简洁的嵌套版本,但是确实认为你清楚地解释了这个概念。 –
@Dispersia我这样做是为了提高可读性。嵌套'选择'很难遵循。在这个例子中,我们必须深入嵌套三个层次,这实在太难理解了。但我同意该解决方案会产生相同的输出。 –
'ForEach'不返回任何东西,所以你的代码不会编译;你不能将'void'分配给'List'。 – Servy
虽然我怀疑这本书是IEnumerable(也许它相当book.Pages和page.Lines?),但我确信Rob已经钉了它。但是,嵌套的SelectMany()调用将是Linq的方式来做到这一点 –
@Rob我看到你张贴答案作为评论很多,人们只是窃取你的答案,为什么不获得你赚的upvotes? – Dispersia