Ruby按索引选择

时间:2016-04-16 18:23:25

标签: arrays ruby

我正在尝试从数组中选择元素:

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]]

请帮助我理解我如何仍然遍历数组并评估索引但只返回元素。

3 个答案:

答案 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"]

注意:

  • 我假设Fibonacci数字从零(而不是一)开始,这是现代定义。
  • Fibonacci序列开始0, 1, 1, 2,...。枚举器index_gen的构建会跳过第二个1
  • index_gen.take_while { |n| n < arr.size } #=> [0, 1, 2, 3, 5, 8, 13]