2010-05-06 19 views
5

Jak mogę zrobić coś jak poniżej?Wielowymiarowe każdy

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

# I want this to return: 

foo 
bar 
baz 
one 
two 
three 
+0

powinien istnieć przecinek po ' 'foo''? –

Odpowiedz

2

Jeśli nie chcesz spłaszczyć tablicy i jeszcze osiągnąć pożądaną funkcjonalność, można zrobić coś takiego:

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]]] 
+0

Naprawdę to lubię! To jest więcej tego, o co prosiłem. – RyanScottLewis

+0

Nie ma problemu! Jeśli chcesz stać się bardziej sprytny, sprawdź: http://github.com/evansenter/y - implementacja Y-combinatora w Ruby (uwaga: większość rubinów nie jest zoptymalizowana pod ogonem, więc przy głębokim zagnieżdżaniu może to mieć problemy z wydajnością). Następnie możesz: 'Y ([1, [2, 3], [4, [5, 6]]]) {| recurser, list | list.respond_to? (: each)? list.each (& recurser): puts (list)} ' Różnica polegająca na braku przypisania zmiennych (a la 'traverser' w powyższym przykładzie). :] –

2

Najłatwiej:

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

Gah! Beat me to ... –

3

można użyć flatten?

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

flatten zwróci kopię tablicy, więc oryginał nie zostanie zmodyfikowany.
Jest również w pełni rekurencyjny, więc nie ma znaczenia, ile macie w macierzy.

+0

stawia, jeśli podano tablicę, wydrukuje każdy element tablicy w osobnej linii. Dlatego "a = [...]; umieszcza a.flatten' może, jeśli trzeba, zamienić pętlę 'each'. –

Powiązane problemy