当前位置:  开发笔记 > 编程语言 > 正文

在Ruby中迭代数组的"正确"方法是什么?

如何解决《在Ruby中迭代数组的"正确"方法是什么?》经验,为你挑选了8个好方法。

对于它的所有瑕疵,PHP在这方面非常好.数组和哈希之间没有区别(也许我很天真,但这对我来说显然是正确的),并且要么迭代你要么做

foreach (array/hash as $key => $value)

在Ruby中有很多方法可以做这种事情:

array.length.times do |i|
end

array.each

array.each_index

for i in array

哈希更有意义,因为我总是使用

hash.each do |key, value|

为什么我不能为数组做这个?如果我只想记住一种方法,我想我可以使用each_index(因为它使索引和值都可用),但是不得不这样做array[index]而烦人value.


哦,对,我忘记了array.each_with_index.然而,这一次吮吸,因为它去|value, key|hash.each|key, value|!这不是疯了吗?



1> Robert Gambl..:

这将迭代所有元素:

array = [1, 2, 3, 4, 5, 6]
array.each { |x| puts x }

打印:

1
2
3
4
5
6

这将迭代所有元素,为您提供值和索引:

array = ["A", "B", "C"]
array.each_with_index {|val, index| puts "#{val} => #{index}" }

打印:

A => 0
B => 1
C => 2

我不太确定你的问题是哪一个.


@CantGetANick:Array类包含具有此方法的Enumerable模块.

2> AShelly..:

我认为没有一个正确的方法.有许多不同的迭代方法,每个方法都有自己的利基.

each 对于许多用法来说已经足够了,因为我并不经常关心索引.

each_ with _index 像Hash#each一样 - 你得到了价值和指数.

each_index - 只是索引.我不经常使用这个.相当于"length.times".

map 是另一种迭代方式,当你想将一个数组转换成另一个数组时非常有用.

select 是您想要选择子集时使用的迭代器.

inject 对于生成总和或产品或收集单个结果非常有用.

记住它可能看起来很多,但不要担心,你可以在不知道所有这些的情况下过去.但是当你开始学习和使用不同的方法时,你的代码将变得更清晰,更清晰,你将会在Ruby的掌握之路上.



3> 小智..:

我不是说Array- > |value,index|Hash- > |key,value|不是疯了(见Horace Loeb的评论),但我说有一种理智的方式来期待这种安排.

当我处理数组时,我专注于数组中的元素(而不是索引,因为索引是暂时的).该方法每个都有索引,即每个+索引,或者|每个索引|,或|value,index|.这也与索引被视为可选参数一致,例如| value | 相当于| value,index = nil | 这与| value,index |一致.

当我处理哈希时,我经常更关注键而不是值,而且我通常按顺序处理键和值,key => value或者hash[key] = value.

如果你想要鸭子打字,那么要么明确地使用Brent Longborough所展示的定义方法,要么使用maxhawkins显示的隐式方法.

Ruby是关于适应程序员的语言,而不是适合语言的程序员.这就是为什么有这么多方法.有很多方法可以考虑某些事情.在Ruby中,您选择最接近的代码,其余的代码通常会非常简洁.

至于最初的问题,"在Ruby中迭代数组的"正确"方法是什么?",我认为核心方式(即没有强大的语法糖或面向对象的权力)是:

for index in 0 ... array.size
  puts "array[#{index}] = #{array[index].inspect}"
end

但Ruby完全是关于强大的语法糖和面向对象的能力,但无论如何这里是等效的哈希,键可以订购或不订购:

for key in hash.keys.sort
  puts "hash[#{key.inspect}] = #{hash[key].inspect}"
end

所以,我的答案是,"在Ruby中迭代数组的"正确"方法取决于你(即程序员或编程团队)和项目." 更好的Ruby程序员可以做出更好的选择(语法能力和/或面向对象的方法).更好的Ruby程序员继续寻找更多方法.


现在,我想问另一个问题,"在Ruby中迭代一个Range的"正确"方法是什么?"!(这个问题是我如何来到这个页面.)

这是很好的(为了前锋):

(1..10).each{|i| puts "i=#{i}" }

但我不喜欢做(向后):

(1..10).to_a.reverse.each{|i| puts "i=#{i}" }

好吧,我实际上并不介意做太多,但是当我教导倒退时,我想向我的学生展示一个很好的对称性(即差异很小,例如只添加一个反向,或一步-1,但没有修改其他任何东西).你可以做(​​对称):

(a=*1..10).each{|i| puts "i=#{i}" }

(a=*1..10).reverse.each{|i| puts "i=#{i}" }

我不太喜欢,但你做不到

(*1..10).each{|i| puts "i=#{i}" }
(*1..10).reverse.each{|i| puts "i=#{i}" }
#
(1..10).step(1){|i| puts "i=#{i}" }
(1..10).step(-1){|i| puts "i=#{i}" }
#
(1..10).each{|i| puts "i=#{i}" }
(10..1).each{|i| puts "i=#{i}" }   # I don't want this though.  It's dangerous

你最终可以做到

class Range

  def each_reverse(&block)
    self.to_a.reverse.each(&block)
  end

end

但我想教纯Ruby而不是面向对象的方法(刚才).我想向后迭代:

没有创建数组(考虑0..1000000000)

适用于任何范围(例如字符串,而不仅仅是整数)

不使用任何额外的面向对象的功率(即没有类修改)

我相信如果没有定义pred方法,这是不可能的,这意味着修改Range类以使用它.如果你能做到这一点,请告诉我,否则将无法确认不可能性,虽然这将是令人失望的.也许Ruby 1.9解决了这个问题.

(感谢您抽出时间阅读本文.)


`1.upto(10)do | i | put i end`和`10.downto(1)do puts i end`有点给出你想要的对称性.希望有所帮助.不确定它是否适用于字符串等.

4> J Cooper..:

需要时同时使用each_with_index.

ary.each_with_index { |val, idx| # ...



5> Pistos..:

其他答案都很好,但我想指出另一个外围的东西:数组是有序的,而哈希不是1.8.(在Ruby 1.9中,Hashes按键的顺序排序.)因此,在1.9之前以与Arrays相同的方式/序列迭代Hash是没有意义的,Arrays总是有一个明确的排序.我不知道PHP关联数组的默认顺序是什么(显然我的google fu还不够强大,但也不知道),但我不知道如何考虑常规PHP数组和PHP关联数组在这种情况下是"相同的",因为关联数组的顺序似乎未定义.

因此,Ruby方式对我来说似乎更加清晰和直观.:)



6> Brent.Longbo..:

尝试与数组和散列一致地做同样的事情可能只是代码气味,但是,如果你正在寻找一致的行为,冒着我被烙为一个有条不紊的半猴子修补程序的风险,这会做的伎俩?

class Hash
    def each_pairwise
        self.each { | x, y |
            yield [x, y]
        }
    end
end

class Array
    def each_pairwise
        self.each_with_index { | x, y |
            yield [y, x]
        }
    end
end

["a","b","c"].each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

{"a" => "Aardvark","b" => "Bogle","c" => "Catastrophe"}.each_pairwise { |x,y|
    puts "#{x} => #{y}"
}



7> Jake..:

以下是您的问题中列出的四个选项,由控制权自由排列.根据您的需要,您可能想要使用不同的一个.

    简单地通过价值观:

    array.each
    

    只需浏览指数:

    array.each_index
    

    通过索引+索引变量:

    for i in array
    

    控制循环计数+索引变量:

    array.length.times do | i |
    



8> Dave Everitt..:

我一直在尝试使用哈希构建菜单(在CampingMarkaby中).

每个项目都有2个元素:一个菜单标签和一个URL,所以哈希似乎是正确的,但'Home'的'/'URL总是出现在最后(正如你所期望的哈希),所以菜单项出现在错误中订购.

使用数组each_slice完成工作:

['Home', '/', 'Page two', 'two', 'Test', 'test'].each_slice(2) do|label,link|
   li {a label, :href => link}
end

为每个菜单项添加额外的值(例如,像CSS ID名称)只是意味着增加切片值.所以,就像一个哈希,但包含任意数量的项目组.完善.

所以这只是感谢你无意中暗示了一个解决方案!

显而易见,但值得一提:我建议检查数组的长度是否可以被切片值整除.

推荐阅读
围脖上的博博_771
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有