2017-01-22 1 views
1

Ich benutze Ruby 2.4. Ich habe ein Array mit String-Datenelementen, die wie folgt aussehenWie kann ich eine Funktion auf ein Array anwenden und zwei separate Arrays bilden?

["a word1 word2", "b eff", "a idaho orange", "new old shoe", "b mars", ...] 

Ich möchte zwei Arrays aus dem obigen bilden, eine Funktion (.split(/^(a|b)[[:space]]*/i) zu jedem Element des Arrays angelegt wird. Ich kann jedoch nicht herausfinden, wie zwei getrennte Arrays gebildet werden. Das folgende

arr.map{ |x| x.split(/^(a|b)[[:space]]*/i) } 

resultiert nur in einem einzelnen Array und hat ein leeres Element vor jedem Element. Im Idealfall würde ich die Ausgabe wie wie zwei Arrays sein

["a", "b", "a", "", "b", ...] 
["word1 word2", "eff", "idaho orange", "new old shoe", "mars", ...] 
+0

Es sei ' "neuen alten Schuh"' 'waren "ein alter Schuh"' oder ' "bold alter Schuh"'? Was würden Sie erwarten, dass der Rückgabewert (in Anbetracht der Tatsache, dass die Regex auf das erste Zeichen dieser beiden Strings aufgeteilt werden würde)? Meinst du '[[: space:]] +' anstatt '[[:: space:]] *'? –

+0

Wenn Sie ein Beispiel geben, 1) machen Sie alle Eingabewerte gültig Ruby-Objekte (keine '" ... "', unter anderem); 2) Weisen Sie allen Eingabeobjekten eine Variable zu (z. B. 'arr = ["a word1 word2", "b eff", "a idaho orange", "neuer alter Schuh", "b mars"]), so dass Leser es können cut and paste, um den Code zu testen und auf diese Variablen ("arr") in Antworten in Kommentaren zu verweisen, ohne sie definieren zu müssen; und 3) zeigen Sie Ihre gewünschte Ausgabe als ein gültiges Ruby-Objekt an (dort sind keine Variablen erforderlich). –

Antwort

2

Versuchen Sie, diese

arr.map { |x| a, b, c = x.partition(/^[ab]\s+/); [b.strip, a + c] }.transpose 

Wie funktionierts?

  • partition teilen eine Zeichenfolge, die vor dem Spiel, Spiel und nach dem Spiel
  • b.strip das Spiel ist ohne Leerzeichen
  • a + c ist nachlauf entweder die vollständige Zeichenfolge (falls es keine Übereinstimmung war die vollständige Zeichenfolge in ist vor dem Spiel) oder der nach dem Spiel
  • [..., ...] ein Tupel
  • transpose schaltet
  • die Zeilen und Spalten eines 2D-Arrays, wodurch die Schaffung einer Anordnung von Tupels schafft
2

Regex nur

Dies ist der kürzeste ich finden konnte:

a1, a2 = arr.map{ |x| x.match(/((?:^[ab](?=))?) *(.*)/).captures}.transpose 

Dieses Beispiel arbeitet jetzt mit "activity" oder "ball". Es prüft, ob direkt nach a oder b am Anfang des Strings ein Leerzeichen folgt.

Split und Logik

Eine andere Variante wäre:

a1, a2 = arr.map do |x| 
    parts = x.split(/(?<=^a|^b) +/) 
    parts.unshift('') if parts.size == 1 
    parts 
end.transpose 
+0

Süß! Vielleicht benutzen Sie auch 'arr.map {| x | x.match (/^([ab]?)? (. *) /). erfasst} .transpose', um die Absicht besser zu kommunizieren. – akuhn

+1

Unde meine dann wieder :) – akuhn

Verwandte Themen