0

因此,通过上述练习并在 GitHub 上找到了这个解决方案。

def count_between arr, lower, upper
  return 0 if arr.length == 0 || lower > upper
  return arr.length if lower == upper
  range = (lower..upper).to_a
  arr.select { |value| range.include?(value) }.length
end

我理解前三行的含义以及它们为什么返回它们所做的值。我想了解的是以下代码行。

第 4 行(下)将“范围”定义为变量,并使用下...上作为范围变量(刚刚发现您不需要将整数值放入范围中。“.to_a”是什么意思,似乎在 ruby​​ 文档中找不到它,它有什么作用?

 range = (lower..upper).to_a

第 5 行(如下)使用 Array#select 方法,如果该值包含在此范围内,则选择此值,然后给我所有选定值的 Array#length,但我不太明白 A. 什么 |价值| 正在做什么以及这意味着什么。B. range.include?(value) 表示这个值是否包含在我假设的这个范围内。

 arr.select { |value| range.include?(value) }.length
4

3 回答 3

6

实际上,我会简化为:

def count_between arr, lower, upper
  return 0 if lower > upper
  arr.count{|v| (lower..upper).include?(v)}
end

to_a记录在这里;它返回一个包含 Range 中每个元素的数组。但是,没有理由在调用to_aRange 之前调用include?.

也没有理由对空数组进行特殊处理。

lower当equals时返回数组的长度是upper没有意义的。

value是为调用块的值赋予的名称。我认为v对于这种微不足道的情况,简单的更好。

select为 in 中的每个值调用块arr并返回一个新数组,其中包含块为其返回的元素true,因此该新数组的长度是匹配值的数量。但是,count它存在并且使用起来更有意义,因为计数是我们所关心的。

更新:正如@steenslag 在评论中指出的那样,Comparable#between? 可以用来代替创建调用的 Range include?,这消除了确保lower小于或等于 的需要upper

def count_between arr, lower, upper
  arr.count{|v| v.between?(lower, upper)}
end
于 2013-05-23T06:56:46.357 回答
1

to_a表示转换为数组

irb(main):001:0> (1..5).to_a
=> [1, 2, 3, 4, 5]

select方法将每个元素传递给块并返回一个新数组,其中包含给定块返回真值的 ary 的所有元素。. 在您的情况下,它只是检查该值是否包含在range数组中。range是一个数组而不是一个范围。

## if arr is [1,5] for eg:

irb(main):005:0> [1,5].select {|value| range.include?(value)}
=> [1, 5]
irb(main):006:0> [1,5].select {|value| range.include?(value)}.length
=> 2

所以 的元素arr包含在|value|块内的变量中。

于 2013-05-23T06:54:54.607 回答
0

这是一个块。

正如文档所说:选择“返回一个新数组,其中包含给定块返回真值的 ary 的所有元素。”

因此,对于其中的每个对象,arr它都被传递给您提供任何您想要返回的代码的块truefalse并且 select 语句使用此结果将值添加到它返回的数组中。之后,length在数组上调用。

所以你有一个数组,你过滤数组以只包含范围内的数字,然后你取长度 - 有效地计算元素的数量。

于 2013-05-23T06:56:12.643 回答