Ruby'de iki dizinin kombinasyonu


82

Aşağıdakileri başarmanın Ruby yolu nedir?

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

Bir dizi istiyorum:

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

@lucasarruda bu, OP'nin sorduğu ile tamamen aynı değil. Zip, bir [a[0], b[0]]ve dizisi oluşturacaktır [a[1], b[1]]. İçermez [a[0], b[1]]. a.zip(b) => [[1,3],[2,4]]
KNejad

Teşekkürler @KNejad, haklısın. Yorumumu sildim.
lucasarruda

Yanıtlar:


149

Önce productdizilerin kartezyen çarpımını elde etmek için kullanabilirsiniz , ardından işlev sonuçlarını toplayabilirsiniz.

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

Böylece sonuçları almak için mapveya kullanabilirsiniz collect. Aynı yöntem için farklı isimlerdir.

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

Ürün yalnızca 1.9 sürümünde yerleşiktir.
Pesto

7
Ürün 1.8.7 sürümünde - Pierr'in istediğini tam olarak yapmak için kullanıyorum
Chris McCauley

1
@ FloatingRock yanlıştır, kombinasyon permüasyon değildir. Ruby-doc.org/core-2.1.3/Array.html#method-i-product
Josh Diehl

1
@FloatingRock Öyle değil. Her öğenin ilk öğesi her zaman ilk listeden, ikinci öğe ikinci listeden vb. Gelir. Tüm olası element kombinasyonlarıdır, ancak asla yeniden sıralanmazlar, bu yüzden permütasyon değildir.
Mark Reed

1
Üç dizi a.product(b,c)ve benzeri için (hafızanız bitene kadar). Ruby çok havalı!
Obromios

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

Not: 1.8.7+ üzerinde 1düzleştirmek için bağımsız değişken olarak ekleyebilirsiniz , böylece fbir dizi döndürdüğünüzde doğru sonuçları almaya devam edersiniz .

İşte rastgele sayıda dizi için bir soyutlama:

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]

Bu işe yarayacak, ancak bunun en iyi yol olup olmadığından emin değilim (ama daha iyisini düşünemiyorum, yani +1)
Robert Massaioli

Keşke keyfi sayıda dizi kombinasyonu için +2 yapabilseydim. Çok havalı!
pierrotlefou

bununla da çıktım .. ama sonra bunun daha kolay bir yol olması gerektiğini biliyordum ... Bunun için +1 ama @Aaron Hinni temizleyiciye cevap veriyor
Orlando

5

Facets has Array#productsize dizilerin çapraz çarpımını verir. Ayrıca, ** operatoriki dizili durum olarak da adlandırılır. Bunu kullanarak şöyle görünecektir:

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

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

Ruby 1.9 kullanıyorsanız, productyerleşik bir Array işlevidir.


İnsanlar neden Array # ürününün 1.9ism olduğunu söyleyip duruyor? En azından 1.8.7'de.
Mark Reed
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.