C# LINQ 中是否有替代 `let` 关键字的强制性替代方法?
Is there an imperative alternative to the `let` keyword in C# LINQ?
在 C# LINQ 中是否有替代 let
关键字的命令?
例如MSDN documentation 中有声明性 LINQ 示例:
var earlyBirdQuery =
from sentence in strings
let words = sentence.Split(' ')
from word in words
let w = word.ToLower()
where w[0] == 'a' || w[0] == 'e'
|| w[0] == 'i' || w[0] == 'o'
|| w[0] == 'u'
select word;
而且我想用命令式的方式来写。可能吗?
我知道我可以做到以下几点:
var earlyBirdQuery = sentence
.Select(s => s.Split(' '))
.Select(w => w.ToLower())
.Where(w => w[0] == 'a' || w[0] == 'e' || w[0] == 'i' || w[0] == 'o' || w[0] == 'u')
.Select(w => w);
是说命令式的Select
具有声明式的from + let
的效果还是有其他方式可以模仿let
和Select
与 from + let
?
不完全相同
在这里,您可以使用 SelectMany
来展平嵌套序列。
char[] vowels = new[] { 'a', 'e', 'i', 'o', 'u' };
var earlyBirdQuery = sentence
.SelectMany(s => s.Split(' '))
.Select(w => w.ToLower())
.Where(w => vowels.Contains(w[0]));
// Result contains all words from all sentences beginning with a vowel.
查询中的第一个 let
并不是必需的,因为您可以简单地写 from word in sentence.Split(' ')
.
您有两个 from
子句。它们的行为很像两个嵌套的 C# for 语句。 SelectMany
打开里面的那个。还有一些情况,你查询一个有集合 属性 的对象,你可以在其中使用 SelectMany
。例如:
// Select all files from all subdirectories of the temp directory.
var directory = new DirectoryInfo(@"c:\temp");
IEnumerable<string> files = directory.GetDirectories()
.SelectMany(d => d.GetFiles())
.Select(f => f.FullName);
或者,SelectMany
的另一个重载具有结果选择器:
var directory = new DirectoryInfo(@"c:\temp");
IEnumerable<string> files = directory.GetDirectories()
.SelectMany(d => d.GetFiles(), (d, f) => f.FullName)
在其他情况下,您可以通过创建匿名类型来存储中间结果。例如:
string[] list = new[] { "A", "B" };
var result = from x in list
let y = x.ToLowerInvariant()
where y == "a"
select x + " " + y;
使用扩展方法语法:
string[] list = new[] { "A", "B" };
var result = list
.Select(x => new { x, y = x.ToLowerInvariant() })
.Where(a => a.y == "a")
.Select(a => a.x + " " + a.y);
在某些情况下,您可以使用语句块来替换 let
:
...
.Where(word => {
string lower = word.ToLower();
return lower.Contains("x") || lower.Contains("y");
})
...
在 C# LINQ 中是否有替代 let
关键字的命令?
例如MSDN documentation 中有声明性 LINQ 示例:
var earlyBirdQuery =
from sentence in strings
let words = sentence.Split(' ')
from word in words
let w = word.ToLower()
where w[0] == 'a' || w[0] == 'e'
|| w[0] == 'i' || w[0] == 'o'
|| w[0] == 'u'
select word;
而且我想用命令式的方式来写。可能吗?
我知道我可以做到以下几点:
var earlyBirdQuery = sentence
.Select(s => s.Split(' '))
.Select(w => w.ToLower())
.Where(w => w[0] == 'a' || w[0] == 'e' || w[0] == 'i' || w[0] == 'o' || w[0] == 'u')
.Select(w => w);
是说命令式的Select
具有声明式的from + let
的效果还是有其他方式可以模仿let
和Select
与 from + let
?
在这里,您可以使用 SelectMany
来展平嵌套序列。
char[] vowels = new[] { 'a', 'e', 'i', 'o', 'u' };
var earlyBirdQuery = sentence
.SelectMany(s => s.Split(' '))
.Select(w => w.ToLower())
.Where(w => vowels.Contains(w[0]));
// Result contains all words from all sentences beginning with a vowel.
查询中的第一个 let
并不是必需的,因为您可以简单地写 from word in sentence.Split(' ')
.
您有两个 from
子句。它们的行为很像两个嵌套的 C# for 语句。 SelectMany
打开里面的那个。还有一些情况,你查询一个有集合 属性 的对象,你可以在其中使用 SelectMany
。例如:
// Select all files from all subdirectories of the temp directory.
var directory = new DirectoryInfo(@"c:\temp");
IEnumerable<string> files = directory.GetDirectories()
.SelectMany(d => d.GetFiles())
.Select(f => f.FullName);
或者,SelectMany
的另一个重载具有结果选择器:
var directory = new DirectoryInfo(@"c:\temp");
IEnumerable<string> files = directory.GetDirectories()
.SelectMany(d => d.GetFiles(), (d, f) => f.FullName)
在其他情况下,您可以通过创建匿名类型来存储中间结果。例如:
string[] list = new[] { "A", "B" };
var result = from x in list
let y = x.ToLowerInvariant()
where y == "a"
select x + " " + y;
使用扩展方法语法:
string[] list = new[] { "A", "B" };
var result = list
.Select(x => new { x, y = x.ToLowerInvariant() })
.Where(a => a.y == "a")
.Select(a => a.x + " " + a.y);
在某些情况下,您可以使用语句块来替换 let
:
...
.Where(word => {
string lower = word.ToLower();
return lower.Contains("x") || lower.Contains("y");
})
...