0
[1,2,3,4,5,6,7].delete_if{|i| i < 4 }

例如,在上面,为什么需要放在|i|before i < 4

我是 Ruby 编程的新手,这个元素的目的让我无法理解。

4

4 回答 4

4

这是块的非常基本的 Ruby 语法。块有时可以采用在条之间给出的参数|。在你的情况下:

[1,2,3,4,5,6,7].delete_if { |i| i < 4 }

delete_if类型的方法Array接受一个块作为参数。当给定块时,块接受数组元素作为参数。因此,i在这种情况下,它会遍历数组中的每个值。更具体地说,如果该元素是 ,则将从数组中删除该元素< 4。结果将是:

[4,5,6,7]

你会经常看到 Ruby 类型方法的文档,例如:

delete_if { |item| block } -> Array

这意味着该方法接受一个带有参数的块,block即使用该参数的一些代码,而输出是另一个数组。该方法的描述在文档中解释了更多细节(例如Ruby Array)。

我建议在线阅读一些 Ruby 入门信息或一本很好的入门书籍,它将更详细地解释这一点。

于 2013-09-13T17:04:32.833 回答
3

您必须将其放在i那里,原因与您i在此处放入第一行的原因相同:

def plus_one(i)
  return i + 1
end

您必须命名您的方法参数,稍后将其用作方法中的局部变量。

Ruby 块类似于方法,它们也可以接收参数,并且声明它们的语法略有不同:将它们包含在| |.

于 2013-09-13T17:35:30.187 回答
1

即使已经回答了 OP 的问题,我也重做了我的答案,因为我想到了一种新的方法来解释这一点,这可能会帮助未来的 SO 用户解决同样的问题。

从高中代数开始,你应该记住这样的函数:f(x) = x + 1.

想象一下在 周围放置花括号x + 1f(x) = { x + 1 }

然后将(x)to 移到花括号内:f = {(x) x + 1 }

然后去掉名字f{(x) x + 1 }。这使它成为“匿名函数”,即“lambda”。

问题是:大括号可能包含任意语句,它们本身可能使用括号:(x + 1) * 4。那么 Ruby 怎么知道(x)应该是函数的参数,而不是要执行的表达式呢?必须使用其他一些语法。因此竖线:|x|。(至少我认为这是思考过程)。

{|i| i > 4 }就像 一样,只是它没有名称并且没有预先定义,因此f(i) = i > 4参数必须定义在函数本身的“内部”,而不是附加到名称之外。

Array#delete_if期望这样一个函数(当它像这样使用时称为“块”)并且知道如何处理它。它将数组的每个成员[1,2,3,4,5,6,7]作为参数传递到块中,i以查看该成员是否i > 4为真。这相当于做这样的事情:

def greater_than_four(x)
  x > 4
end
arr = [1,2,3,4,5,6,7]
arr.each do |el|
  arr.delete(el) if greater_than_four(el)
end

greater_than_four您可以通过动态定义 lambda来避免提前定义方法,如下所示:

arr = [1,2,3,4,5,6,7]
arr.each do |el|
  arr.delete(el) if lambda{|i| i > 4}.call(el)
end

但是由于Array#delete_if已经期望一个块,并且已经知道在每个元素上调用它,您可以为自己节省大量代码:

[1,2,3,4,5,6,7].delete_if{|i| i < 4 }
于 2013-09-13T20:55:45.697 回答
0

您传递给该delete_if方法的参数是一个块,而您传递给该块的参数内部的东西。

将块视为一种方法。该delete_if方法遍历块并将当前项作为参数i传递给块。如果条件评估为真,则该元素将被删除。

于 2013-09-13T17:07:19.873 回答