通过上述练习,在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行(下面)将“range”定义为变量,并使用lower ... upper作为范围变量(刚发现你不需要在一个范围内放置一个整数值。'。to_a是什么'意思是,似乎无法在ruby文档中找到它,它做了什么?
range = (lower..upper).to_a
第5行(下面)使用的是一个Array#select方法,如果该值包含在此范围内,则选择此值,然后给出所有选定值的数组#长度,但我不太了解A什么|价值|正在做什么,它意味着什么。 B. range.include?(value)表示此值包含在我假设的范围内。
arr.select { |value| range.include?(value) }.length
答案 0 :(得分:6)
实际上,我会对此进行简化:
def count_between arr, lower, upper
return 0 if lower > upper
arr.count{|v| (lower..upper).include?(v)}
end
记录了{p> to_a
here;它返回一个包含Range中每个元素的Array。但是,在调用to_a
之前,没有理由在Range上调用include?
。
也没有理由对空数组进行特殊处理。
当lower
等于upper
时,返回数组的长度毫无意义。
value
是为块调用的值赋予的名称。我认为一个简单的v
对于这样一个微不足道的案例更好。
select
为arr
中的每个值调用块,并返回一个新的Array,其中包含块返回true
的元素,因此新数组的长度是匹配值。但是,count
存在,并且使用更有意义,因为计数是我们所关心的。
更新:正如@steenslag在评论中指出的那样,可以使用Comparable#between?代替创建要调用include?
的范围,这样就无需确保lower
小于或等于upper
:
def count_between arr, lower, upper
arr.count{|v| v.between?(lower, upper)}
end
答案 1 :(得分:1)
to_a
表示转换为数组
irb(main):001:0> (1..5).to_a
=> [1, 2, 3, 4, 5]
select方法将每个元素传递给块,返回一个新数组,其中包含给定块返回true值的所有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|
变量中。
答案 2 :(得分:0)
这是一个障碍。
正如文档所说:select“返回一个新数组,其中包含给定块返回true值的所有ary元素。”
因此,对于arr
中的每个对象,它将传递给您提供所需代码的块,该代码将返回true
或false
,并且select语句将此结果用于将值添加到它返回的数组。之后,在数组上调用length
。
所以你有一个数组,你过滤数组只包含范围内的数字,然后你取长度 - 有效地计算元素的数量。