2017-12-21 4 views
1

Ich möchte eine Zeichenfolge in zwei Teile trennen, wenn ein Token aus einem Array am Ende der Zeichenfolge gefunden wird. Ich habe dies versucht:Wie spalte ich ein Token vom Ende meiner Zeichenfolge?

x = "Canton Female" 
GENDER_TOKENS = ["m", "male", "men", "f", "w", "female", "wom"] 

x.partition(/(^|[[:space:]]+)[#{Regexp.union(GENDER_TOKENS)}]$/i) 
#=> ["Canton Female", "", ""] 

Aber obwohl das Wort „weiblich“ Teil meines Tokens ist, ist es nicht spalten sich immer. Wie stelle ich meine Regex so ein, dass sie richtig geteilt wird?

+1

Welchen Wert möchten Sie zurück? –

+1

Sie machen den gleichen Fehler: Sie verwenden 'Regexp.union' in einem Regex-Literal und das' i' beeinflusst diese Änderungen nicht. Außerdem fügst du diese Gruppe in eine Zeichenklasse ein und es ruiniert das Muster insgesamt. Nicht sicher, was du hier brauchst, siehe [diese Demo] (https://ideone.com/jCz5le), probiere 'x.partition (/ (?:^| [[:: Space:]] +) (?: # { Regexp.union (GENDER_TOKENS) .source}) $/i) ' –

Antwort

3

Ich bin ein wenig unklar, was Sie fragen - was ist das gewünschte Ergebnis? Aber hier ist, was ich denke, Sie suchen:

GENDER_TOKENS = ["m", "male", "men", "f", "w", "female", "wom"] 

"Canton Female".split(/\b(#{Regexp.union(GENDER_TOKENS).source})$/i) 
#=> => ["Canton ", "Female"] 

"Tom Lord".split(/\b(#{Regexp.union(GENDER_TOKENS).source})$/i) 
#=> => ["Tom Lord"] 
  • String#split wird die Zeichenfolge auf jedem Match aufgeteilt; im Gegensatz zu String#partition, die [head, match, tail] zurückgibt. I denke, das ist wahrscheinlich, was Sie wollten?
  • \b ist ein Wortgrenzenanker. Dies ist eine sauberere Lösung, als wenn versucht wird, auf "Anfang der Zeile oder Leerzeichen" zu passen.
  • Die Regexp Union ist in Runde Klammern eingewickelt, um die Werte zusammen zu gruppieren, nicht eckige Klammern. Letzteres macht es zu einem Zeichensatz, der eindeutig nicht das ist, was Sie wollten.
  • Regexp#source gibt nur den inneren "Text" des regexp zurück; im Gegensatz zu der (impliziten) Regexp#to_s Sie verwendet haben, die die volle Objekt einschließlich Option schaltet zurück - das heißt /(?-mix:m|male|men|f|w|female|wom)/
+0

Bemerkenswert das ursprüngliche Beispiel hatte den' Regexp.union' Teil innerhalb '[...]' Klammern (Satz von Zeichen), die es völlig anders verhält. – tadman

2

Warum zuerst nicht geteilt?

parts = x.split 
if GENDER_TOKENS.include? parts.last.downcase 
    # ... 
end 

Wahrscheinlich nicht viel langsamer und Weise besser lesbar

1
GENDER_TOKENS = %w[m male men f w female wom] 
GENDER_REGEX = /\b(?:#{GENDER_TOKENS.join('|')})\z/i 
    #=> /\b(?:m|male|men|f|w|female|wom)\z/i 

def split_off_token(str) 
    idx = str =~ GENDER_REGEX 
    case idx 
    when nil 
    [str] 
    when 0 
    ['', str] 
    else 
    [str[0, idx].rstrip, str[idx..-1]] 
    end 
end 

split_off_token("Canton Female") 
    #=> ["Canton", "Female"] 
split_off_token("Canton M") 
    #=> ["Canton", "M"] 
split_off_token("wom") 
    #=> ["", "wom"] 
split_off_token("Canton Fella") 
    #=> ["Canton Fella"] 
Verwandte Themen