each 和 par-each
each 对列表的每一项(或表格的每一行)运行一个闭包,并返回结果的列表。par-each 做的事情相同,但会同时对多个项运行闭包。
each
闭包会同时通过参数与 $in 接收到当前项:
[1 2 3] | each {|x| $x * 10 }
# => ╭───┬────╮
# => │ 0 │ 10 │
# => │ 1 │ 20 │
# => │ 2 │ 30 │
# => ╰───┴────╯
[1 2 3] | each { $in * 10 }
# => ╭───┬────╮
# => │ 0 │ 10 │
# => │ 1 │ 20 │
# => │ 2 │ 30 │
# => ╰───┴────╯对于表格,每一项是一行(一个记录):
[[name size]; [a 1kb] [b 2kb]] | each {|row| $"($row.name): ($row.size)" }
# => ╭───┬───────────╮
# => │ 0 │ a: 1.0 kB │
# => │ 1 │ b: 2.0 kB │
# => ╰───┴───────────╯关于 each 如何处理输入与输出的一些细节:
当闭包返回
null时,该结果会被略过。使用--keep-empty(-k)可以改为保留一个空单元格:[1 2 3] | each {|x| if $x != 2 { $x * 10 } } # => ╭───┬────╮ # => │ 0 │ 10 │ # => │ 1 │ 30 │ # => ╰───┴────╯ [1 2 3] | each --keep-empty {|x| if $x != 2 { $x * 10 } } # => ╭───┬────╮ # => │ 0 │ 10 │ # => │ 1 │ │ # => │ 2 │ 30 │ # => ╰───┴────╯当闭包返回列表时,结果是一个列表的列表。使用
--flatten(-f)可以得到单个扁平列表:[a b] | each --flatten {|x| [$x $x] } # => ╭───┬───╮ # => │ 0 │ a │ # => │ 1 │ a │ # => │ 2 │ b │ # => │ 3 │ b │ # => ╰───┴───╯区间会像列表一样被迭代。
null输入会原样返回,不会运行闭包。闭包内不能使用
break和continue(它不是循环)。请改用for, 或者用take while或each while提前停止——后者会在遇到第一个null结果时停止:[1 2 3 4] | each while {|x| if $x < 3 { $x * 10 } } # => ╭───┬────╮ # => │ 0 │ 10 │ # => │ 1 │ 20 │ # => ╰───┴────╯
遍历记录
each/par-each 只迭代列表/表格数据。记录是单个值,所以 each 只会以整个记录运行闭包一次。 要遍历记录中的每个键/值对,请使用 items:
{a: 1, b: 2} | items {|key, value| $"($key)=($value)" }
# => ╭───┬─────╮
# => │ 0 │ a=1 │
# => │ 1 │ b=2 │
# => ╰───┴─────╯或者先用 | transpose key value 把记录转成一张键/值的表格。
示例:
{name: "Nushell", lang: "Rust", stars: 38000}
| transpose key value
| inspect
| each {|kv|
$'The value of the "($kv.key)" field is "($kv.value)"'
}
# => ╭─────────────┬───────────────────────────────────────────────╮
# => │ description │ table<key: string, value: oneof<string, int>> │
# => ├─────────────┴───────────────┬───────────────────────────────┤
# => │ key │ value │
# => ├─────────────────────────────┼───────────────────────────────┤
# => │ name │ Nushell │
# => │ lang │ Rust │
# => │ stars │ 38000 │
# => ╰─────────────────────────────┴───────────────────────────────╯
# =>
# => ╭───┬────────────────────────────────────────────╮
# => │ 0 │ The value of the "name" field is "Nushell" │
# => │ 1 │ The value of the "lang" field is "Rust" │
# => │ 2 │ The value of the "stars" field is "38000" │
# => ╰───┴────────────────────────────────────────────╯par-each
par-each 接受与 each 相同类型的闭包,但会用线程池在多个项上并行运行它。 当闭包执行的是耗时操作(例如运行外部命令或读取文件)时,这会很有帮助。 对于很快的闭包,each 通常一样快。
- 结果按完成顺序返回。使用
--keep-order(-k)可以按输入顺序得到结果。 - 使用
--threads(-t)设置线程数。
[1 2 3 4 5] | par-each --keep-order {|x| $x * 2 }
# => ╭───┬────╮
# => │ 0 │ 2 │
# => │ 1 │ 4 │
# => │ 2 │ 6 │
# => │ 3 │ 8 │
# => │ 4 │ 10 │
# => ╰───┴────╯另见《Nushell 之书》中的并行。