What is the “right” way to iterate through an array in Ruby?

后端 未结 12 1719
盖世英雄少女心
盖世英雄少女心 2020-12-04 04:18

PHP, for all its warts, is pretty good on this count. There\'s no difference between an array and a hash (maybe I\'m naive, but this seems obviously right to me), and to ite

相关标签:
12条回答
  • 2020-12-04 05:08

    Trying to do the same thing consistently with arrays and hashes might just be a code smell, but, at the risk of my being branded as a codorous half-monkey-patcher, if you're looking for consistent behaviour, would this do the trick?:

    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}"
    }
    
    0 讨论(0)
  • 2020-12-04 05:10

    This will iterate through all the elements:

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

    Prints:

    1
    2
    3
    4
    5
    6
    

    This will iterate through all the elements giving you the value and the index:

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

    Prints:

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

    I'm not quite sure from your question which one you are looking for.

    0 讨论(0)
  • 2020-12-04 05:13

    Use each_with_index when you need both.

    ary.each_with_index { |val, idx| # ...
    
    0 讨论(0)
  • 2020-12-04 05:16

    Here are the four options listed in your question, arranged by freedom of control. You might want to use a different one depending on what you need.

    1. Simply go through values:

      array.each
      
    2. Simply go through indices:

      array.each_index
      
    3. Go through indices + index variable:

      for i in array
      
    4. Control loop count + index variable:

      array.length.times do | i |
      
    0 讨论(0)
  • 2020-12-04 05:19

    I think there is no one right way. There are a lot of different ways to iterate, and each has its own niche.

    • each is sufficient for many usages, since I don't often care about the indexes.
    • each_ with _index acts like Hash#each - you get the value and the index.
    • each_index - just the indexes. I don't use this one often. Equivalent to "length.times".
    • map is another way to iterate, useful when you want to transform one array into another.
    • select is the iterator to use when you want to choose a subset.
    • inject is useful for generating sums or products, or collecting a single result.

    It may seem like a lot to remember, but don't worry, you can get by without knowing all of them. But as you start to learn and use the different methods, your code will become cleaner and clearer, and you'll be on your way to Ruby mastery.

    0 讨论(0)
  • 2020-12-04 05:21

    I'd been trying to build a menu (in Camping and Markaby) using a hash.

    Each item has 2 elements: a menu label and a URL, so a hash seemed right, but the '/' URL for 'Home' always appeared last (as you'd expect for a hash), so menu items appeared in the wrong order.

    Using an array with each_slice does the job:

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

    Adding extra values for each menu item (e.g. like a CSS ID name) just means increasing the slice value. So, like a hash but with groups consisting of any number of items. Perfect.

    So this is just to say thanks for inadvertently hinting at a solution!

    Obvious, but worth stating: I suggest checking if the length of the array is divisible by the slice value.

    0 讨论(0)
提交回复
热议问题