是否可以单独声明传递到注入方法块中的数组元素的块参数?
Is it possible to separately declare block parameters of an array element which is passed into a block for the inject method?
这是我现在正在做的目前有效的,但我觉得有点缺乏语法糖...
f = RGeo::Geos.factory
coords = [ [1,1], [2,2], [1,3] ]
points = coords.inject([]) {|points, coord| points << f.point(coord[0], coord[1]); points }
#=> [#<RGeo::Geos::CAPIPointImpl:0x3fff0950a508 "POINT (1.0 1.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a47c "POINT (2.0 2.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a454 "POINT (1.0 3.0)">]
这是我想做的事情:
points = coords.inject([]) {|points, x, y| points << f.point(x,y); points }
#=> [nil, nil, nil]
现在返回一个包含三个 nil 值的数组。是否可以像使用 each 方法那样分别声明传递到注入块中的元素的数组值?
旁注:
为第一个注入块参数("result" 变量)和等号左侧的变量使用相同的变量名是安全的,对吧?我想是的,因为这只是一个典型的递归案例。如果您有其他感受或知道,请发表评论。
这样做就可以了:
points = coords.inject([]) {|points, (x, y)| points << f.point(x,y); points }
这通常适用于任何区块;如果其中一个块参数是 n 个元素的数组,您可以使用 n 个带括号的参数名称捕获这些元素。如果在括号中使用超过 n 个参数名称,则额外的将为 nil:
[[1,2,3],[4,5]].map {|(a,b,c)| "#{a}+#{b}+#{c.inspect}" } #=> ["1+2+3", "4+5+nil"]
如果您使用的参数名称太少,剩余部分将被丢弃:
[[1,2,3],[4,5]].map {|(a,b)| "#{a}+#{b}" } #=> ["1+2", "4+5"]
您可以使用 splat 运算符来捕获余数,就像使用常规参数一样:
[[1,2,3],[4,5]].map {|(a,*b)| "#{a}+#{b}" } #=> ["1+[2, 3]", "4+[5]"]
你甚至可以嵌套:
[[1,2,[3,4]],[5,6,[7,8]]].map {|(a,b,(c,d))| a+b+c+d } #=> [10, 26]
请注意,嵌套它很快就会造成混淆,因此请谨慎使用。
另请注意,严格来说,这些外括号在上述示例中并不是必需的,但当仅从数组中获取一个参数时,它们会改变行为:
# Makes no difference
[[1,2,3],[4,5,6]].map {| a,b,c | "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"]
[[1,2,3],[4,5,6]].map {|(a,b,c)| "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"]
# Makes a big difference
[[1,2,3],[4,5,6]].map {| a | a } #=> [[1, 2, 3], [4, 5, 6]]
[[1,2,3],[4,5,6]].map {|(a)| a } #=> [1, 4]
这是我现在正在做的目前有效的,但我觉得有点缺乏语法糖...
f = RGeo::Geos.factory
coords = [ [1,1], [2,2], [1,3] ]
points = coords.inject([]) {|points, coord| points << f.point(coord[0], coord[1]); points }
#=> [#<RGeo::Geos::CAPIPointImpl:0x3fff0950a508 "POINT (1.0 1.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a47c "POINT (2.0 2.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a454 "POINT (1.0 3.0)">]
这是我想做的事情:
points = coords.inject([]) {|points, x, y| points << f.point(x,y); points }
#=> [nil, nil, nil]
现在返回一个包含三个 nil 值的数组。是否可以像使用 each 方法那样分别声明传递到注入块中的元素的数组值?
旁注: 为第一个注入块参数("result" 变量)和等号左侧的变量使用相同的变量名是安全的,对吧?我想是的,因为这只是一个典型的递归案例。如果您有其他感受或知道,请发表评论。
这样做就可以了:
points = coords.inject([]) {|points, (x, y)| points << f.point(x,y); points }
这通常适用于任何区块;如果其中一个块参数是 n 个元素的数组,您可以使用 n 个带括号的参数名称捕获这些元素。如果在括号中使用超过 n 个参数名称,则额外的将为 nil:
[[1,2,3],[4,5]].map {|(a,b,c)| "#{a}+#{b}+#{c.inspect}" } #=> ["1+2+3", "4+5+nil"]
如果您使用的参数名称太少,剩余部分将被丢弃:
[[1,2,3],[4,5]].map {|(a,b)| "#{a}+#{b}" } #=> ["1+2", "4+5"]
您可以使用 splat 运算符来捕获余数,就像使用常规参数一样:
[[1,2,3],[4,5]].map {|(a,*b)| "#{a}+#{b}" } #=> ["1+[2, 3]", "4+[5]"]
你甚至可以嵌套:
[[1,2,[3,4]],[5,6,[7,8]]].map {|(a,b,(c,d))| a+b+c+d } #=> [10, 26]
请注意,嵌套它很快就会造成混淆,因此请谨慎使用。
另请注意,严格来说,这些外括号在上述示例中并不是必需的,但当仅从数组中获取一个参数时,它们会改变行为:
# Makes no difference
[[1,2,3],[4,5,6]].map {| a,b,c | "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"]
[[1,2,3],[4,5,6]].map {|(a,b,c)| "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"]
# Makes a big difference
[[1,2,3],[4,5,6]].map {| a | a } #=> [[1, 2, 3], [4, 5, 6]]
[[1,2,3],[4,5,6]].map {|(a)| a } #=> [1, 4]