2011-12-16 5 views
-2

Как я могу пойти с этим:Как переплетать элементы из двух массивов?

for number in [1,2] do 
    puts 1+number 
    puts 2+number 
    puts 3+number 
end 

который вернет 2,3,4 затем 3,4,5 -> 2,3,4,3,4,5. Это всего лишь пример, и явно не реальное использование.

Вместо этого, я бы хотел, чтобы он вернулся 2,3 3,4 4,5 -> 2,3,3,4,4,5. Я хотел бы, чтобы каждый из puts был итерирован для каждого из возможных значений числа; В этом случае 1 и 2 являются двумя возможными значениями «число», прежде чем переходить к следующим позициям.

Один из способов сделать это, чтобы создать два списка, [2,3,4] и [3,4,5], а затем использовать метод zip объединить их как [2,3,4].zip([3,4,5]) -> [2,3,3,4,4,5].

ответ

2

zip хорошее. Вы также должны смотреть на each_cons:

1.9.2p290 :006 > [2,3,4].each_cons(2).to_a 
=> [[2, 3], [3, 4]] 
1.9.2p290 :007 > [2,3,4,5,6].each_cons(2).to_a 
=> [[2, 3], [3, 4], [4, 5], [5, 6]] 
1.9.2p290 :008 > [2,3,4,5,6].each_cons(3).to_a 
=> [[2, 3, 4], [3, 4, 5], [4, 5, 6]] 

Потому что each_cons возвращает нумератор, вы можете использовать блок с ним, как указано в документации к нему, или преобразовать его в массив с помощью to_a, как я сделал выше. Это возвращает массив массивов, которые могут быть уплощенным, чтобы получить один массив:

[2,3,4,5].each_cons(2).to_a.flatten 
=> [2, 3, 3, 4, 4, 5] 

Из ri документов:

итерацию данного блока для каждого массива последовательных элементов. Если нет блока , возвращается перечислитель.

e.g.: 
    (1..10).each_cons(3) {|a| p a} 
    # outputs below 
    [1, 2, 3] 
    [2, 3, 4] 
    [3, 4, 5] 
    [4, 5, 6] 
    [5, 6, 7] 
    [6, 7, 8] 
    [7, 8, 9] 
    [8, 9, 10] 
0

Может быть, не самый читаемый код, но вы можете использовать Inject на первом диапазоне, чтобы создать массив, основанный на суммированном до второго диапазона.

(1..3).inject([]){|m,n| (1..2).each{|i| m<<n+i }; m } 
=> [2, 3, 3, 4, 4, 5] 

Это может быть немного более читаемым

res=[] 
(1..3).each{|r1| (1..2).each{|r2| res<<r1+r2 } }