Ruby中使用each_with_index与index的用例

时间:2015-04-06 03:40:12

标签: ruby arrays

Ruby的新手;当我使用数组时,Enumerable#each_with_indexArray#index之间是否有区别我一直在使用多维数组,我试图找到给定值的位置。当我使用其中任何一个时,我的代码都能够通过所有测试。坐标是我用来保存给定值的位置的数组(在本例中为1)

field=[[1,0],[0,0]]
coordinates=[]  
field.each_with_index do |item|
  if item.index(1)
    coordinates.push(field.index(item)).push(item.index(1))
  end
end

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:5)

让我们仔细看看你的代码:

field=[[1,0],[0,0]]
coordindates = []  
field.each_with_index do |item|
  if item.index(1)
    coordinates.push(field.index(item)).push(item.index(1))
  end
end

让:

enum = field.each_with_index
  #=> #<Enumerator: [[1, 0], [0, 0]]:each_with_index>

如您所见,这将返回一个枚举器。

Ruby看到你的代码如下:

enum.each do |item|
  if item.index(1)
    coordinates.push(field.index(item)).push(item.index(1))
  end
end

枚举器的元素将由Enumerator#each传递到块中,由于接收者field是类Array的实例,因此将调用Array#each

我们可以通过将enum转换为数组来查看enum.to_a #=> [[[1, 0], 0], [[0, 0], 1]] 的元素:

each

如你所见,它有两个元素,每个元素都是两个元素的数组,第一个是两个整数的数组,第二个是整数。

我们可以通过向enum发送Enumerator#next并将块变量分配给next返回的值来模拟item的操作。由于只有一个块变量item = enum.next #=> [[1, 0], 0] ,我们有:

item

这很可能既不是你期望的也不是你想要的。

接下来,您在item.index(1) #=> nil 上调用Array#index

index

item在数组1中搜索等于item.index(0) #=> 1的元素。如果找到一个,则返回该数组中该元素的索引。 (例如,[1,0])。由于01都不等于indexnil会返回field.each_with_index do |item, index|...

让我们回放(并重新创建枚举器)。您需要两个块变量:

enum.each do |item, index|...

与:

相同
item, index = enum.next
      #=> [[1, 0], 0] 
item  #=> [1, 0] 
index #=> 0 

现在:

item.index(1)
  #=> 0

field.each_with_index do |(first, second), index|...

我会让你从这里拿走它,但让我再说一件事。我不是在提倡它,但你可以写:

(first, second), index = enum.next
       #=> [[1, 0], 0] 
first  #=> 1
second #=> 0 
index  #=> 0

在这种情况下:

{{1}}

答案 1 :(得分:1)

请参阅Ruby doc:http://ruby-doc.org/core-2.2.0/Array.html#method-i-indexhttp://ruby-doc.org/core-2.2.1/Enumerable.html#method-i-each_with_index

indexArray的一种方法,它会检测项目是否存在于特定Array中,如果项目存在则返回索引,nil如果不存在则返回存在。

each_with_indexEnumerable mixin的方法,通常需要2个参数,第一个是item,第二个是index。

因此,您的样本可以简化为:

field = [[1, 0], [0, 0]]
coordinates = []
field.each_with_index do |item, index|
  item_index = item.index(1)
  coordinates << index << item_index if item_index
end
puts coordinates.inspect # => [0, 0]

请注意,field.index(item)只是index

答案 2 :(得分:1)

Array#indexEnumerable#each_with_index无关联(从功能上讲),一个用于获取数组中对象的索引,另一个用于遍历集合。

实际上each_with_indexeach方法的变异,它还会产生集合中实际对象的索引。如果您需要跟踪所在对象的当前位置,此方法非常有用。它可以省去创建和增加其他变量的麻烦。

例如

['a', 'b', 'c', 'd'].each_with_index do|char, idx|
     puts "#{idx}) #{char}"
end

输出:

0) a
1) b
2) c
3) d

没有each_with_index

idx = 0
['a', 'b', 'c', 'd'].each do|char|
     puts "#{idx}) #{char}"
     idx += 1
end

输出:

0) a
1) b
2) c
3) d

要在多维数组中查找对象的索引,您必须至少迭代矩阵的所有行,如下所示(使用each_with_indexindex

def find_position(matrix, obj)
     matrix.each_with_index do|row, i|
          return [i, j] if j = row.index(obj)
     end
     return nil
end

例如:

find_position([[2,3],[4,5]], 5)  #  => [1, 1]

答案 3 :(得分:1)

鉴于:

fields = [[1, 0], [0, 0]]

Enumerable#each_with_index将每个索引以及每个对象传递给块:

fields.each_with_index do |field, idx|
  puts "#{field}, #{idx}"
end

#=> [1, 0], 0
#=> [0, 0], 1

Array#index返回匹配数组元素的索引:

puts fields.index([1, 0])

#=> 0