views:

74

answers:

3

How would I do something like below?

[
    'foo'
    ['bar', 'baz'],
    [
        'one',
        ['two', 'three']
    ]
].each { |word| puts word }

# I want this to return:

foo
bar
baz
one
two
three
+2  A: 

The easiest way:

words = ['foo',['bar', 'baz'],['one',['two', 'three']]]
words.flatten.each{ |word| puts word }
perimosocordiae
Gah! Beat me to it...
Carson Myers
+3  A: 

Could you use flatten?

[
    'foo'
    ['bar', 'baz'],
    [
        'one',
        ['two', 'three']
    ]
].flatten.each { |word| puts word }

flatten will return a copy of the array, so the original won't be modified.
It's also fully recursive so it doesn't matter how many arrays-within-arrays you have.

Carson Myers
puts, if given an array, will print each element of the array on a separate line. Therefore, `a = [...] ; puts a.flatten` can, if desired, replace the `each` loop.
Wayne Conrad
+1  A: 

If you don't want to flatten the array and still achieve the desired functionality, you can do something like:

irb(main):016:0> array = [1, [2, 3], [4, [5, 6]]]
=> [1, [2, 3], [4, [5, 6]]]
irb(main):017:0> (traverser = lambda { |list| list.respond_to?(:each) ? list.each(&traverser) : puts(list) })[array]
1
2
3
4
5
6
=> [1, [2, 3], [4, [5, 6]]]
Evan Senter
I really like this! This is more of what I was asking for.
c00lryguy
Evan Senter