31 Stimmen

Kombiniere Array von Array in alle möglichen Kombinationen, nur vorwärts, in Ruby

Ich habe ein Array von Arrays, etwa so:

[['1','2'],['a','b'],['x','y']]

Ich muss diese Arrays zu einer Zeichenkette kombinieren, die alle möglichen Kombinationen aller drei Sätze enthält, nur in Vorwärtsrichtung. Ich habe viele Beispiele für alle möglichen Kombinationen der Gruppen in beliebiger Reihenfolge gesehen, aber das ist nicht das, was ich will. Ich möchte zum Beispiel nicht, dass irgendeines der Elemente in der ersten Gruppe nach der zweiten Gruppe kommt, oder dass irgendeines in der dritten Gruppe vor der ersten oder zweiten Gruppe kommt, und so weiter. Für das obige Beispiel würde die Ausgabe also lauten:

['1ax', '1ay', '1bx', '1by', '2ax', '2ay', '2bx', '2by']

Die Anzahl der Arrays und die Länge der einzelnen Sets ist dynamisch.

Weiß jemand, wie man dieses Problem in Ruby lösen kann?

0 Stimmen

Mögliches Duplikat von Mehrere Iterationen

0 Stimmen

62voto

Andrew Grimm Punkte 73882

Wissen Ihr Array#product :

a = [['1','2'],['a','b'],['x','y']]
a.first.product(*a[1..-1]).map(&:join)

0 Stimmen

@Travis: Wenn dies Ihre Frage beantwortet, können Sie das Häkchen neben der Frage setzen.

0 Stimmen

Bei mir funktioniert es nicht: Ich erhalte nur ['1ax', '2by'] :/

1 Stimmen

@AndrewGrimm Die Antwort mit transpose nicht das Richtige getan haben; ich habe Ihre Antwort bearbeitet, um sie zu entfernen.

10voto

Phrogz Punkte 283167

Gelöst mit einer rekursiven, so genannten "Dynamische Programmierung" Ansatz:

  • Bei n Feldern kombinieren Sie die Einträge des ersten Feldes mit jedem Ergebnis der übrigen (n-1) Felder
  • Für ein einzelnes Array ist die Antwort genau dieses Array

Im Code:

def variations(a)
  first = a.first
  if a.length==1 then
    first
  else
    rest = variations(a[1..-1])
    first.map{ |x| rest.map{ |y| "#{x}#{y}" } }.flatten
  end
end

p variations([['1','2'],['a','b'],['x','y']])
#=> ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"]

puts variations([%w[a b],%w[M N],['-'],%w[x y z],%w[0 1 2]]).join(' ')
#=> aM-x0 aM-x1 aM-x2 aM-y0 aM-y1 aM-y2 aM-z0 aM-z1 aM-z2 aN-x0 aN-x1 aN-x2
#=> aN-y0 aN-y1 aN-y2 aN-z0 aN-z1 aN-z2 bM-x0 bM-x1 bM-x2 bM-y0 bM-y1 bM-y2
#=> bM-z0 bM-z1 bM-z2 bN-x0 bN-x1 bN-x2 bN-y0 bN-y1 bN-y2 bN-z0 bN-z1 bN-z2

Sie können die Logik auch umkehren, und mit etwas Sorgfalt sollten Sie in der Lage sein, dies nicht-rekursiv zu implementieren. Aber die rekursive Antwort ist ziemlich einfach :)

6voto

Sply Splyeff Punkte 81

Rein, mit Produkt reduzieren:

a = [['1','2'],['a','b'],['x','y']]
a.reduce() { |acc, n| acc.product(n).map(&:flatten) }.map(&:join)
#  => ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X