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.