Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby中的基本数组迭代_Ruby_Arrays - Fatal编程技术网

Ruby中的基本数组迭代

Ruby中的基本数组迭代,ruby,arrays,Ruby,Arrays,在遍历另一个数组的同时遍历该数组的更好方法是什么?例如,如果我有两个数组,如下所示: names = [ "Rover", "Fido", "Lassie", "Calypso"] breeds = [ "Terrier", "Lhasa Apso", "Collie", "Bulldog"] index = 0 names.each do |name| Dog.new("#{name}", "#{breeds[index]}") index = index.next end 假设

在遍历另一个数组的同时遍历该数组的更好方法是什么?例如,如果我有两个数组,如下所示:

names = [ "Rover", "Fido", "Lassie", "Calypso"]
breeds = [ "Terrier", "Lhasa Apso", "Collie", "Bulldog"]
index = 0

names.each do |name|
  Dog.new("#{name}", "#{breeds[index]}")
  index = index.next
end
假设数组彼此对应-即,漫游者是一只梗,Fido是拉萨Apso,等等-我想为每个项目创建一个dog类和一个新的dog对象:

class Dog
  attr_reader :name, :breed

  def initialize(name, breed)
    @name = name
    @breed = breed
  end
end
我可以通过以下方式重复名称和品种:

names = [ "Rover", "Fido", "Lassie", "Calypso"]
breeds = [ "Terrier", "Lhasa Apso", "Collie", "Bulldog"]
index = 0

names.each do |name|
  Dog.new("#{name}", "#{breeds[index]}")
  index = index.next
end
然而,我觉得使用索引变量是错误的。有什么更好的办法

dogs = names.zip(breeds).map { |name, breed| Dog.new(name, breed) }
Array#zip
将目标数组与参数元素交错,因此

irb> [1, 2, 3].zip(['a', 'b', 'c'])
 #=> [ [1, 'a'], [2, 'b'], [3, 'c'] ]
您可以使用不同长度的数组(在这种情况下,目标数组确定结果数组的长度,并用
nil
填充额外的条目)

您还可以将两个以上的阵列压缩在一起:

irb> [1,2,3].zip(['a', 'b', 'c'], [:alpha, :beta, :gamma])
 #=> [ [1, 'a', :alpha], [2, 'b', :beta], [3, 'c', :gamma] ]
Array#map
是转换数组的好方法,因为它返回一个数组,其中每个条目都是在目标数组中相应条目上运行块的结果

irb> [1,2,3].map { |n| 10 - n }
 #=> [ 9, 8, 7 ]
在数组数组上使用迭代器时,如果给定多参数块,数组项将自动分解为以下参数:

irb> [ [1, 'a'], [2, 'b'], [3, 'c'] ].each { |array| p array }
[ 1, 'a' ]
[ 2, 'b' ]
[ 3, 'c' ]
#=> nil
irb> [ [1, 'a'], [2, 'b'], [3, 'c'] ].each do |num, char| 
...>   puts "number: #{num}, character: #{char}" 
...> end
number 1, character: a
number 2, character: b
number 3, character: c
#=> [ [1, 'a'], [2, 'b'], [3, 'c'] ]
比如,
#每个带有_索引的_
是另一个需要了解的好工具。它遍历数组的元素,依次为每个元素传递一个块

irb> ['a', 'b', 'c'].each_with_index do |char, index| 
...>   puts "character #{char} at index #{index}"
...> end
character a at index 0
character b at index 1
character c at index 2
#=> [ 'a', 'b', 'c' ]
使用迭代器(如
#each_with_index
)时,可以使用括号将数组元素分解为其组成部分:

irb> [ [1, 'a'], [2, 'b'], [3, 'c'] ].each_with_index do |(num, char), index| 
...>   puts "number: #{num}, character: #{char} at index #{index}" 
...> end
number 1, character: a at index 0
number 2, character: b at index 1
number 3, character: c at index 2
#=> [ [1, 'a'], [2, 'b'], [3, 'c'] ]

突然想到,这是一个更好的方式做它的方式,你正在做它。不过,rampion有一个更好的总体答案,这种情况就是zip的用途。

这是改编自Flanagan和Matz,“Ruby编程语言”,5.3.5“外部迭代器”,示例5-1,第页。139:

++++++++++++++++++++++++++++++++++++++++++

require 'enumerator'  # needed for Ruby 1.8

names = ["Rover", "Fido", "Lassie", "Calypso"]  
breeds = ["Terrier", "Lhasa Apso", "Collie", "Bulldog"]

class Dog  
    attr_reader :name, :breed  

    def initialize(name, breed)  
        @name = name  
        @breed = breed  
    end  
end

def bundle(*enumerables)  
    enumerators = enumerables.map {|e| e.to_enum}  
    loop {yield enumerators.map {|e| e.next} }  
end  

bundle(names, breeds) {|x| p Dog.new(*x) }  
+++++++++++++++++++++++++++++++++++++++++++

require 'enumerator'  # needed for Ruby 1.8

names = ["Rover", "Fido", "Lassie", "Calypso"]  
breeds = ["Terrier", "Lhasa Apso", "Collie", "Bulldog"]

class Dog  
    attr_reader :name, :breed  

    def initialize(name, breed)  
        @name = name  
        @breed = breed  
    end  
end

def bundle(*enumerables)  
    enumerators = enumerables.map {|e| e.to_enum}  
    loop {yield enumerators.map {|e| e.next} }  
end  

bundle(names, breeds) {|x| p Dog.new(*x) }  
输出:

#<Dog:0x10014b648 @name="Rover", @breed="Terrier">  
#<Dog:0x10014b0d0 @name="Fido", @breed="Lhasa Apso">  
#<Dog:0x10014ab80 @name="Lassie", @breed="Collie">  
#<Dog:0x10014a770 @name="Calypso", @breed="Bulldog">  
#
#  
#  
#  

我想这就是我们想要的

以及
每个带有_索引的
(Matt提到),还有
每个_索引
。我有时使用它是因为它使程序更加对称,因此会产生错误的代码


+1:这绝对是一个值得了解的好工具,而不是维护您自己的索引变量。这也是一个非常好的解决方案,还可以返回对象及其属性。谢谢这个循环让我头晕目眩,直到一些研究揭示了它是如何工作的。按照Pickaxe的说法,“循环默默地拯救了StopIteration异常,它与外部迭代器配合得很好。”太好了!