2010-10-22 5 views
27

Ich habe eine schöne CamelCase-Zeichenfolge wie ImageWideNice oder ImageNarrowUgly. Nun möchte ich diese Kette in ihren Teilsträngen brechen, wie Image, Wide oder Narrow, und Nice oder Ugly.Wie teilt man einen CamelCase String in seine Teilstrings in Ruby auf?

dachte ich, das einfach durch

gelöst werden könnte
camelCaseString =~ /(Image)((Wide)|(Narrow))((Nice)|(Ugly))/ 

Aber seltsam, diese $1 und $2 nur füllen, aber nicht $3.

Haben Sie eine bessere Idee, diese Zeichenfolge zu teilen?

+1

Was möchten Sie mit ThisIsANarrowImageOfHIV tun? Machen Sie eine Verbindung mit n, oder teilen Sie HIV auf? –

Antwort

50
s = 'nowIsTheTime' 

s.split /(?=[A-Z])/ 

=> ["now", "Is", "The", "Time"] 

?=pattern ist ein Beispiel für positive Vorschau. Es entspricht im Wesentlichen einem Punkt in der Zeichenfolge direkt vor Muster. Es verbraucht nicht die Zeichen, das heißt, es enthält Muster als Teil des Spiels nicht. Ein weiteres Beispiel:

irb> 'streets'.sub /t(?=s)/, '-' 
=> "stree-s" 

In diesem Fall wird die s abgestimmt ist (nur die zweiten t Streichhölzer), aber nicht ersetzt. Dank @Bryce und sein regexp doc link. Bryce Anderson fügt eine Erklärung:

Die ?= zu Beginn der () Match Gruppe positiven Look-Ahead genannt wird, das zu sagen, dass nur ein Weg ist, während die regex ist suchen bei den Zeichen in der Bestimmung, ob es übereinstimmt, ist es nicht machen sie Teil des Spiels. split() isst normalerweise die dazwischen liegenden Zeichen, aber in diesem Fall ist die Übereinstimmung selbst leer, also gibt es nichts [dort].

+1

Haben Sie 'NowIsTheTime' probiert? – splash

+1

@splash: Es funktioniert immer noch gut – ryeguy

+0

Während meiner Tests diese Regex ergibt "[" "," Now "," Ist "," The "," Time "]' wenn der erste Buchstabe ein Großbuchstabe ist. Was mache ich falsch? – splash

2

Haben Sie

versucht
camelCaseString =~ /(Image)(Wide|Narrow)(Nice|Ugly)/ 

?

2

Ereignis obwohl dies ein Ruby ist regex Frage und die answer by DigitalRoss ist richtig und glänzt durch seine Einfachheit, ich möchte eine Java Antwort hinzuzufügen:

// this regex doesn't work perfect with Java and other regex engines 
"NowIsTheTime".split("(?=[A-Z])"); // ["", "Now", "Is", "The", "Time"] 

// this regex works with first uppercase or lowercase characters 
"NowIsTheTime".split("(?!(^|[a-z]|$))"); // ["Now", "Is", "The", "Time"] 
"nowIsTheTime".split("(?!(^|[a-z]|$))"); // ["now", "Is", "The", "Time"] 
27

Ich weiß, das ist alt, aber es lohnt sich für andere zu erwähnen, die könnte nach diesem suchen. In Schienen können Sie dies tun: "NowIsTheTime".underscore.humanize

5

DigitalRoss Antwort ist korrekt, da es den allgemeinen Fall behandelt, wo Sie nicht wissen, ob es strenge Kamel Fall (erstes Zeichen Kleinbuchstaben) oder Pascal Fall (Großbuchstaben Anfangsbuchstabe) ist.

Wenn Sie wissen, in welchen Formen die Zeichenkette liegt, oder Sie die eine oder andere Form erzwingen wollen, kann Inflector es tun.

Für Pascal Fall:

"NowIsTheTime".titleize 

Für Kamel Fall:

"nowIsTheTime".titleize.camelize :lower 
+0

Wichtig zu beachten, '# titleize' und' # camelize' sind streng Rails-Methoden und nicht im Kern Ruby. – onebree

0

Die Antwort von DigitalRoss nicht eingebettet Akronyme in der Camelcase erkennen. Zum Beispiel wird "MyHTMLTricks" in "My H T M L Tricks" anstelle von "My HTML Tricks" aufgeteilt.

Hier ist eine weitere Option auf der Grundlage der AsSpaced() Funktion in PmWiki, die von empfindlich auf Fälle wie diese ganze Arbeit:

"MyHTMLTricks" \ 
.gsub(/([[:lower:]\\d])([[:upper:]])/, '\1 \2') \ 
.gsub(/([^-\\d])(\\d[-\\d]*(|$))/,'\1 \2') \ 
.gsub(/([[:upper:]])([[:upper:]][[:lower:]\\d])/, '\1 \2') 

=> "My HTML Tricks" 

Die andere Sache, die ich an diesem Ansatz ist, dass es die Zeichenfolge verläßt eine Zeichenfolge, anstatt sie in ein Array umzuwandeln. Wenn Sie das Array wirklich wollen, fügen Sie am Ende einfach einen Split hinzu.

"MyHTMLTricks" \ 
.gsub(/([[:lower:]\\d])([[:upper:]])/, '\1 \2') \ 
.gsub(/([^-\\d])(\\d[-\\d]*(|$))/,'\1 \2') \ 
.gsub(/([[:upper:]])([[:upper:]][[:lower:]\\d])/, '\1 \2') \ 
.split 

=> ["My", "HTML", "Tricks"] 

Für den Rekord, hier ist der ursprüngliche PHP-Code von PmWiki.

function AsSpaced($text) { 
    $text = preg_replace("/([[:lower:]\\d])([[:upper:]])/", '$1 $2', $text); 
    $text = preg_replace('/([^-\\d])(\\d[-\\d]*(|$))/', '$1 $2', $text); 
    return preg_replace("/([[:upper:]])([[:upper:]][[:lower:]\\d])/", '$1 $2', $text); 
} 
Verwandte Themen