如何在没有负索引的情况下迭代ruby数组

时间:2016-12-22 08:08:25

标签: arrays ruby data-structures iteration

我需要将ruby数组中的每个值与上一个和下一个值进行比较。

更新

实施例

[1,2,4,5]

我想这样检查一下。 (a[i] with a[i-1] and a[i+1])

1 with only next value  # as there is no prev value
2 with prev & next value
4 with prev & next value
5 with only prev value # as there is no next value

在ruby中,a [-1]没有指向nil,它取最后一个值。所以,无法迭代。有没有其他解决方案?

试过

  1. 将数组更改为[nil,1,2,4,5,nil]
  2. 但得到以下错误

      

    Fixnum与nil的比较失败(ArgumentError)

    1. 而不是0..n我尝试1...n。但这并没有解决我的问题。
    2. 问题:

      如何忽略ruby数组中第一个(i-1)和最后一个(i + 1)元素的负索引。

3 个答案:

答案 0 :(得分:3)

你的比较并没有多大意义。你正在比较所有的东西两次,但如果有人真的正在迭代它时你正在改变数组,你会遇到比这更大的问题(你仍然不会捕获对数组开头的修改)当你已经在中间)。足以比较每个连续的元素对,这很容易做到:

[1, 2, 4, 5].each_cons(2).all? {|a, b| a < b }

如果你真的绝对必须比较三元组,那也很容易做到:

[1, 2, 4, 5].each_cons(3).all? {|a, b, c| a < b && b < c }

如果你想让滑动窗口的大小通用,那么你可以这样做:

[1, 2, 4, 5].each_cons(n).all? {|window| 
  window.each_cons(2).map {|a, b| a < b }.inject(:&) 
}

答案 1 :(得分:2)

  

我需要将ruby数组中的每个值与previous和next进行比较   值。

此方法采用数组和比较方法,例如:<:>:==

def prev_next arr, com
  arr.map.with_index { |e,i|
    if i == 0
      [ e,
        e.send(com,arr[i.succ])
      ]
    elsif i == arr.length-1
      [ e.send(com,arr[i.pred]),
        e
      ]
    else
      [ e.send(com,arr[i.pred]),
        e, 
        e.send(com,arr[i.succ])
      ]
    end
  }
end

arr = [1,2,3,4,5]
p prev_next(arr,:<)
#=> [[1, true], [false, 2, true], [false, 3, true], [false, 4, true], [false, 5]]

注意第二个参数可以作为字符串或符号传递,因为send足够聪明,可以将字符串转换为符号。

值得注意的方法:Object#sendFixnum#succInteger#pred

答案 2 :(得分:1)

现在我完全同意Jörg的观点,each_cons是要走的路,如果比较数据这么复杂,你应该寻找其他数据结构。

随着说。没有什么能阻止Ruby中的正常索引查找,如果没有其他工作,只需在简单的case语句中实现您的需求:

my_array = [1,2,4,5]

my_array.size.times do |ix|
    case ix
      when 0 then my_array[ix] == my_array[ix+1]
      when my_array.size-1 then my_array[ix] == my_array[ix-1]
      else my_array[ix-1] == my_array[ix] == my_array[ix+1]
    end
end