我正在尝试从数组中选择元素:
arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']
其索引是斐波纳契数。我想要结果:
['a', 'b', 'c', 'd', 'f', 'i', 'n']
我的代码返回元素和索引。
def is_fibonacci?(i, x = 1, y = 0)
return true if i == x || i == 0
return false if x > i
is_fibonacci?(i, x + y, x)
end
arr.each_with_index.select do |val, index|
is_fibonacci?(index)
end
此代码返回:
[["a", 0], ["b", 1], ["c", 2], ["d", 3], ["f", 5], ["i", 8], ["n", 13]]
请帮助我理解我如何仍然遍历数组并评估索引但只返回元素。
答案 0 :(得分:19)
您可以将代码的最后一位更改为
arr.select.with_index do |val, index|
is_fibonacci?(index)
end
这是有效的,因为如果你在没有块的情况下调用select
这样的方法,你会得到一个Enumerator
对象,然后你可以在其上链接更多的Enumerable方法。
在这种情况下,我使用了with_index
,这与在原始数组上调用each_with_index
非常相似。但是因为这发生在select
之后而不是之前,select
会返回原始数组中的项目,而不会附加索引
答案 1 :(得分:1)
到目前为止,您的代码似乎很棒,我不会改变它。您可以在事后检查结果,并将[element, index]
对更改为仅element
mapping对每一对,并且仅取first:
>> results = [["a", 0], ["b", 1], ["c", 2], ["d", 3], ["f", 5], ["i", 8], ["n", 13]]
>> results.map(&:first)
=> ["a", "b", "c", "d", "f", "i", "n"]
答案 2 :(得分:1)
这是另一种方法。
index_gen = Enumerator.new do |y|
i = 0
j = 1
loop do
y.yield i unless i==j
i, j = j, i + j
end
end
#=> #<Enumerator: #<Enumerator::Generator:0x007fa3eb979028>:each>
arr.values_at(*index_gen.take_while { |n| n < arr.size })
#=> ["a", "b", "c", "d", "f", "i", "n"]
或
index_gen.take_while { |n| n < arr.size }.map { |n| arr[n] }
#=> ["a", "b", "c", "d", "f", "i", "n"]
注意:
0, 1, 1, 2,...
。枚举器index_gen
的构建会跳过第二个1
。index_gen.take_while { |n| n < arr.size } #=> [0, 1, 2, 3, 5, 8, 13]