Поєднання двох масивів у Ruby


82

Який спосіб Ruby досягти?

a = [1,2]
b = [3,4]

Я хочу масив:

=> [f(1,3) ,f(1,4) , f(2,3) ,f(2,4)]

@lucasarruda, це не зовсім те саме, що запитує OP. Zip створить масив [a[0], b[0]]та [a[1], b[1]]. Це не включало б [a[0], b[1]]. a.zip(b) => [[1,3],[2,4]]
KNejad

Дякую @KNejad, ви праві. Видалив мій коментар.
lucasarruda

Відповіді:


149

productСпочатку можна отримати декартовий добуток масивів, а потім зібрати результати функції.

a.product(b) => [[1, 3], [1, 4], [2, 3], [2, 4]]

Таким чином, ви можете використовувати mapабо, collectщоб отримати результати. Це різні назви одного і того ж методу.

a.product(b).collect { |x, y| f(x, y) }

Продукт вбудований лише з 1.9.
Песто

7
Продукт знаходиться в версії 1.8.7 - я використовую його, щоб робити саме те, що просить П'єр
Кріс МакКолі

1
Неправильний @FloatingRock - це комбінація, а не перестановка. Дивіться ruby-doc.org/core-2.1.3/Array.html#method-i-product
Джош Діл

1
@FloatingRock Не так. Перший елемент кожного елемента завжди надходитиме з першого списку, другий елемент з другого списку тощо. Це всі можливі комбінації елементів, але вони ніколи не впорядковуються, тому це не перестановки.
Mark Reed

1
На три масиви a.product(b,c)і так далі (поки не вичерпається пам’ять). Рубі така крута!
Оброміос

11
a.map {|x| b.map {|y| f(x,y) } }.flatten

Примітка: На версії 1.8.7+ ви можете додати 1як аргумент для вирівнювання, тому ви все одно отримуватимете правильні результати, коли fповертаєте масив.

Ось абстракція для довільної кількості масивів:

def combine_arrays(*arrays)
  if arrays.empty?
    yield
  else
    first, *rest = arrays
    first.map do |x|
      combine_arrays(*rest) {|*args| yield x, *args }
    end.flatten
      #.flatten(1)
  end
end

combine_arrays([1,2,3],[3,4,5],[6,7,8]) do |x,y,z| x+y+z end
# => [10, 11, 12, 11, 12, 13, 12, 13, 14, 11, 12, 13, 12, 13, 14, 13, 14, 15, 12, 13, 14, 13, 14, 15, 14, 15, 16]

Це спрацює, хоча я не впевнений, що це найкращий спосіб (хоча не можу придумати кращого, тому +1)
Роберт Массайолі

Я хотів би +2 для комбінації довільної кількості масивів. Дуже круто!
pierrotlefou

я теж вийшов із цим .. але тоді я знав, що це повинен бути простіший спосіб зробити це ... +1 за це, але @Aaron Hinni відповідає на прибиральницю
Орландо

5

Фасети має, Array#productякі дадуть вам перехресний добуток масивів. Це також псевдонім як ** operatorдля двомасивного випадку. Використовуючи це, це буде виглядати так:

require 'facets/array'
a = [1,2]
b = [3,4]

(a.product b).collect {|x, y| f(x, y)}

Якщо ви використовуєте Ruby 1.9, productце вбудована функція Array.


Чому люди постійно кажуть, що продукт Array # - це 1,9-ізм? Це принаймні 1.8.7.
Марк Рід
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.