Kombination zweier Arrays in Ruby


82

Was ist der Ruby-Weg, um Folgendes zu erreichen?

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

Ich möchte ein Array:

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

@ Lucasarruda, das ist nicht ganz das Gleiche wie das, was OP verlangt. Zip erstellt ein Array von [a[0], b[0]]und [a[1], b[1]]. Es würde nicht enthalten [a[0], b[1]]. a.zip(b) => [[1,3],[2,4]]
KNejad

Danke @KNejad, du bist richtig. Mein Kommentar wurde gelöscht.
Lucasarruda

Antworten:


147

Sie können verwenden product, um zuerst das kartesische Produkt der Arrays abzurufen und dann die Funktionsergebnisse zu erfassen.

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

So können Sie mapoder verwenden collect, um die Ergebnisse zu erhalten. Sie sind unterschiedliche Namen für dieselbe Methode.

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

Produkt ist erst ab 1.9 eingebaut.
Pesto

7
Produkt ist in 1.8.7 - Ich benutze es, um genau das zu tun, was Pierr verlangt
Chris McCauley

1
@FloatingRock, das ist falsch, es ist eine Kombination, keine Permutation. Siehe ruby-doc.org/core-2.1.3/Array.html#method-i-product
Josh Diehl

1
@FloatingRock Nicht so. Das erste Element jedes Elements stammt immer aus der ersten Liste, das zweite Element aus der zweiten Liste usw. Es sind alles mögliche Kombinationen von Elementen, aber sie werden nie neu angeordnet, es sind also keine Permutationen.
Mark Reed

Und wenn Sie c = [5,6] und d = [7,8] haben, können Sie tun[a,b,c,d].reduce([[]]){|r,e| r=r.product(e)}.map{|x| x.flatten}
xxjjnn

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

Hinweis: Ab Version 1.8.7 können Sie 1ein Argument zum Reduzieren hinzufügen , damit Sie bei der fRückgabe eines Arrays immer noch korrekte Ergebnisse erhalten .

Hier ist eine Abstraktion für eine beliebige Anzahl von Arrays:

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]

Dies wird funktionieren, obwohl ich nicht sicher bin, ob es der beste Weg ist (obwohl ich mir keinen besseren
vorstellen

Ich wünschte, ich könnte +2 für die Kombination einer beliebigen Anzahl von Arrays. Sehr cool!
Pierrotlefou

Ich kam auch damit heraus .. aber dann wusste ich, dass es einen einfacheren Weg geben sollte, es zu tun ... +1 dafür, aber der @ Aaron Hinni antwortet seinem Reiniger
Orlando

5

Facetten hat, Array#productdie Ihnen das Kreuzprodukt von Arrays geben. Es wird auch als Alias ** operatorfür den Fall mit zwei Arrays verwendet. Damit würde es so aussehen:

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

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

Wenn Sie Ruby 1.9 verwenden, productist dies eine integrierte Array-Funktion.


Warum sagen die Leute immer wieder, dass das Array # -Produkt ein 1.9ismus ist? Zumindest in 1.8.7.
Mark Reed
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.