Was ist angesichts der Zeichenfolge "ThisStringHasNoSpacesButItDoesHaveCapitals" der beste Weg, Leerzeichen vor den Großbuchstaben hinzuzufügen. Die Endzeichenfolge wäre also "Diese Zeichenfolge hat keine Leerzeichen, aber Großbuchstaben".
Hier ist mein Versuch mit einem RegEx
System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0")
Antworten:
Die regulären Ausdrücke werden gut funktionieren (ich habe sogar die Antwort von Martin Browns gewählt), aber sie sind teuer (und ich persönlich finde jedes Muster länger als ein paar Zeichen, die unerschwinglich stumpf sind).
Diese Funktion
Wird es 100.000 Mal in 2.968.750 Ticks tun, wird der Regex 25.000.000 Ticks nehmen (und das ist mit dem kompilierten Regex).
Es ist besser, für einen bestimmten Wert von besser (dh schneller), aber es ist mehr Code zu pflegen. "Besser" ist oft ein Kompromiss zwischen konkurrierenden Anforderungen.
Hoffe das hilft :)
Aktualisieren
Es ist lange her, dass ich mir das angesehen habe, und ich habe gerade festgestellt, dass die Timings nicht aktualisiert wurden, seit sich der Code geändert hat (es hat sich nur wenig geändert).
Bei einer Zeichenfolge, bei der 'Abbbbbbbbb' 100 Mal wiederholt wird (dh 1.000 Byte), werden bei einer Konvertierung von 100.000 Konvertierungen die handcodierte Funktion 4.517.177 Ticks ausgeführt, und bei der folgenden Regex werden 59.435.719 Ticks ausgeführt, sodass die handcodierte Funktion in 7,6% der Zeit ausgeführt wird Regex.
Update 2 Werden Akronyme berücksichtigt? Es wird jetzt! Die Logik der if-Anweisung ist ziemlich dunkel, wie Sie sehen können, wenn Sie sie auf diese ...
... hilft überhaupt nicht!
Hier ist die ursprüngliche einfache Methode, die sich nicht um Akronyme kümmert
quelle
Ihre Lösung hat das Problem, dass vor dem ersten Buchstaben T ein Leerzeichen steht, damit Sie erhalten
Um dies zu umgehen, suchen Sie auch nach dem vorangestellten Kleinbuchstaben und fügen Sie dann das Leerzeichen in der Mitte ein:
Bearbeiten 1:
Wenn Sie es verwenden
@"(\p{Ll})(\p{Lu})"
, werden auch Zeichen mit Akzent aufgenommen.Bearbeiten 2:
Wenn Ihre Zeichenfolgen Akronyme enthalten können, können Sie Folgendes verwenden:
"DriveIsSCSICompatible" wird also zu "Drive Is SCSI Compatible".
quelle
"([^A-Z\\s])([A-Z])"
mit Akronymen verwenden?Leistung nicht getestet, aber hier in einer Zeile mit linq:
quelle
Ich weiß, dass dies eine alte ist, aber dies ist eine Erweiterung, die ich verwende, wenn ich dies tun muss:
Dies ermöglicht Ihnen die Verwendung
MyCasedString.ToSentence()
quelle
TrimStart(' ')
, wird der führende Leerzeichen entfernt.SelectMany
die einen Index enthält. Auf diese Weise werden der erste Buchstabe und der unnötige potenzielle Aufwand für einen zusätzlichen Aufruf von vermiedenTrimStart(' ')
. Rauben.Willkommen bei Unicode
Alle diese Lösungen sind für modernen Text im Wesentlichen falsch. Sie müssen etwas verwenden, das den Fall versteht. Da Bob nach anderen Sprachen gefragt hat, gebe ich ein paar für Perl.
Ich biete vier Lösungen an, die vom schlechtesten bis zum besten reichen. Nur der Beste hat immer Recht. Die anderen haben Probleme. Hier ist ein Testlauf, der Ihnen zeigt, was funktioniert und was nicht und wo. Ich habe Unterstriche verwendet, damit Sie sehen können, wo die Leerzeichen platziert wurden, und ich habe alles, was falsch ist, als falsch markiert.
Übrigens hat fast jeder hier den ersten Weg gewählt, den mit "Schlimmsten" gekennzeichneten. Einige haben den zweiten Weg mit "OK" gewählt. Aber niemand vor mir hat Ihnen gezeigt, wie man entweder den "besseren" oder den "besten" Ansatz macht.
Hier ist das Testprogramm mit seinen vier Methoden:
Wenn Sie in diesem Datensatz das gleiche Ergebnis wie "Best" erzielen können, wissen Sie, dass Sie es richtig gemacht haben. Bis dahin hast du nicht. Niemand hier hat es besser gemacht als "Ok", und die meisten haben es "am schlechtesten" gemacht. Ich freue mich darauf, jemanden zu sehen, der den richtigen post-Code veröffentlicht.
Ich stelle fest, dass der Hervorhebungscode von StackOverflow wieder miserabel dumm ist. Sie machen alle die gleichen alten Lahmheiten wie (die meisten, aber nicht alle) der anderen armen Ansätze, die hier erwähnt wurden. Ist es nicht lange her, ASCII zur Ruhe zu bringen? Es macht keinen Sinn mehr und so zu tun, als wäre es alles, was Sie haben, ist einfach falsch. Es macht für schlechten Code.
quelle
Ich habe mich vorgenommen, eine einfache Erweiterungsmethode zu erstellen, die auf dem Code von Binary Worrier basiert und Akronyme richtig verarbeitet und wiederholbar ist (bereits verteilte Wörter werden nicht entstellt). Hier ist mein Ergebnis.
Hier sind die Unit-Testfälle, die diese Funktion besteht. Ich habe die meisten von tchrist vorgeschlagenen Fälle zu dieser Liste hinzugefügt. Die drei von denen, die es nicht besteht (zwei sind nur römische Ziffern), sind auskommentiert:
quelle
Binary Worrier, ich habe Ihren vorgeschlagenen Code verwendet, und es ist ziemlich gut, ich habe nur eine kleine Ergänzung dazu:
Ich habe eine Bedingung hinzugefügt
!char.IsUpper(text[i - 1])
. Dies behebt einen Fehler, der dazu führen würde, dass etwas wie "AverageNOX" in "Average NO X" umgewandelt wird, was offensichtlich falsch ist, da es "Average NOX" lauten sollte.Leider hat dies immer noch den Fehler, dass Sie, wenn Sie den Text 'FromAStart' haben, 'From AStart' herausbekommen würden.
Irgendwelche Gedanken zur Behebung dieses Problems?
quelle
if (char.IsUpper(text[i]) && !(char.IsUpper(text[i - 1]) && char.IsUpper(text[i + 1])))
Testergebnis: "Von Anfang an", "Von Anfang an", "Von Anfang an", aber Sie müsseni < text.Length - 1
in der for-Schleifenbedingung das letzte Zeichen ignorieren und eine Ausnahme außerhalb des Bereichs verhindern.Hier ist meins:
quelle
<pre><code>code</code></pre>
Block anstelle der Markdown-Syntax versteckt . Keine Notwendigkeit, ihn abzustimmen (wenn das du warst).Stellen Sie sicher , Sie sind nicht setzen Leerzeichen am Anfang des Strings, aber Sie werden sie zwischen aufeinanderfolgenden Großbuchstaben setzen. Einige der Antworten hier sprechen nicht einen oder beide dieser Punkte an. Es gibt andere Möglichkeiten als Regex, aber wenn Sie dies bevorzugen, versuchen Sie Folgendes:
Das
\B
ist ein negiertes\b
, also stellt es eine Nicht-Wort-Grenze dar. Dies bedeutet, dass das Muster mit "Y" übereinstimmtXYzabc
, jedoch nicht mitYzabc
oderX Yzabc
. Als kleinen Bonus können Sie dies für eine Zeichenfolge mit Leerzeichen verwenden, ohne diese zu verdoppeln.quelle
Dieser Regex setzt ein Leerzeichen vor jeden Großbuchstaben:
Achten Sie auf den Platz vor "$ 1 $ 2", dies wird es tun.
Dies ist das Ergebnis:
quelle
"([A-Z0-9])([a-z]*)"
Was Sie haben, funktioniert perfekt. Denken Sie daran,
value
den Rückgabewert dieser Funktion neu zuzuweisen .quelle
Hier erfahren Sie, wie Sie dies in SQL tun können
quelle
Inspiriert von @MartinBrown, Two Lines of Simple Regex, das Ihren Namen auflöst, einschließlich Acyronyms an einer beliebigen Stelle in der Zeichenfolge.
quelle
quelle
quelle
In Ruby über Regexp:
quelle
Ich nahm Kevin Strikers ausgezeichnete Lösung und konvertierte zu VB. Da ich an .NET 3.5 gebunden bin, musste ich auch IsNullOrWhiteSpace schreiben. Dies besteht alle seine Tests.
quelle
Die Frage ist etwas alt, aber heutzutage gibt es auf Nuget eine nette Bibliothek, die genau dies tut, sowie viele andere Konvertierungen in von Menschen lesbaren Text.
Schauen Sie sich Humanizer auf GitHub oder Nuget an.
Beispiel
quelle
Scheint eine gute Gelegenheit für
Aggregate
. Dies soll lesbar sein, nicht unbedingt besonders schnell.quelle
Zusätzlich zu Martin Browns Antwort hatte ich auch ein Problem mit Zahlen. Zum Beispiel: "Location2" oder "Jan22" sollte "Location 2" bzw. "Jan 22" sein.
Hier ist mein regulärer Ausdruck dafür, der Martin Browns Antwort verwendet:
Hier sind ein paar großartige Seiten, um herauszufinden, was jeder Teil auch bedeutet:
Java Based Regular Expression Analyzer (funktioniert aber für die meisten .net-Regex)
Action Script Based Analyzer
Der obige reguläre Ausdruck funktioniert auf der Aktionsskript-Site nur, wenn Sie alle
\p{Ll}
mit[a-z]
, die\p{Lu}
mit[A-Z]
und\p{Nd}
mit ersetzen[0-9]
.quelle
Hier ist meine Lösung, basierend auf dem Vorschlag von Binary Worriers und dem Einbau von Richard Priddys 'Kommentaren, aber auch unter Berücksichtigung, dass in der bereitgestellten Zeichenfolge möglicherweise Leerzeichen vorhanden sind, sodass kein Leerzeichen neben dem vorhandenen Leerzeichen hinzugefügt wird.
quelle
Für alle, die nach einer C ++ - Funktion suchen, die dieselbe Frage beantwortet, können Sie Folgendes verwenden. Dies ist der Antwort von @Binary Worrier nachempfunden. Diese Methode behält Akronyme nur automatisch bei.
Die Testzeichenfolgen, die ich für diese Funktion verwendet habe, und die Ergebnisse sind:
quelle
Eine C # -Lösung für eine Eingabezeichenfolge, die nur aus ASCII-Zeichen besteht. Die Regex enthält ein negatives Lookbehind , um einen Großbuchstaben (Großbuchstaben) zu ignorieren, der am Anfang der Zeichenfolge angezeigt wird. Verwendet Regex.Replace () , um die gewünschte Zeichenfolge zurückzugeben.
Siehe auch die Demo zu regex101.com .
Erwartete Ausgabe:
Update: Hier ist eine Variante, die auch Akronyme (Sequenzen von Großbuchstaben) behandelt.
Siehe auch die Demo von regex101.com und die Demo von ideone.com .
Erwartete Ausgabe:
quelle
Hier ist eine gründlichere Lösung, bei der keine Leerzeichen vor den Wörtern stehen:
Hinweis: Ich habe mehrere Regexs verwendet (nicht präzise, aber es werden auch Akronyme und Wörter mit einem Buchstaben verarbeitet).
In :
Out :
quelle
Alle vorherigen Antworten sahen zu kompliziert aus.
Ich hatte eine Zeichenfolge, die eine Mischung aus Großbuchstaben und _ so verwendet, string.Replace (), um das _, "" zu erstellen, und verwendete das Folgende, um ein Leerzeichen an den Großbuchstaben hinzuzufügen.
quelle
Inspiriert von der Antwort von Binary Worrier nahm ich einen Schwung.
Hier ist das Ergebnis:
Test mit Stoppuhr mit 10000000 Iterationen und verschiedenen Stringlängen und -kombinationen.
Im Durchschnitt 50% (vielleicht etwas mehr) schneller als die Antwort von Binary Worrier.
quelle
quelle
Dieser enthält Akronyme und Akronympluralformen und ist etwas schneller als die akzeptierte Antwort:
Besteht diese Tests:
quelle
Eine Implementierung mit
fold
, auch bekannt alsAggregate
:Zusätzlich zur Anforderung speichert diese Implementierung korrekt führende, innere, nachfolgende Leerzeichen und Akronyme, z.
quelle
Eine einfache Möglichkeit, Leerzeichen nach Kleinbuchstaben, Großbuchstaben oder Ziffern einzufügen.
quelle