So schreiben Sie den ersten Buchstaben eines Strings in Ruby groß

134

Die upcaseMethode schreibt die gesamte Zeichenfolge groß, aber ich muss nur den ersten Buchstaben groß schreiben.

Außerdem muss ich einige beliebte Sprachen wie Deutsch und Russisch unterstützen.

Wie mache ich es?

AntonAL
quelle
4
Beachten Sie, dass einige Sprachen unterschiedliche Vorstellungen davon haben, wie der erste Buchstabe groß geschrieben werden soll. Auf Irisch machen Sie Dinge wie "i mBaile Átha Cliath" ("in Dublin") - Kleinbuchstaben "m", Großbuchstaben "B". (Siehe en.wikipedia.org/wiki/Consonant_mutation#Celtic_languages, wenn Sie neugierig sind, warum Iren das tun würden und warum es Sinn macht.)
James Moore
3
Und beachten Sie auch, dass #capitalize alle Buchstaben in Kleinbuchstaben schreibt, die nicht der erste Buchstabe sind ... was nicht immer das ist, was Sie wollen. ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Huliax

Antworten:

260

Es hängt davon ab, welche Ruby-Version Sie verwenden:

Ruby 2.4 und höher:

Es funktioniert einfach, da Ruby v2.4.0 die Unicode- Fallzuordnung unterstützt:

"мария".capitalize #=> Мария

Ruby 2.3 und niedriger:

"maria".capitalize #=> "Maria"
"мария".capitalize #=> мария

Das Problem ist, es macht einfach nicht das, was Sie wollen, es gibt марияstattdessen statt Мария.

Wenn Sie Rails verwenden, gibt es eine einfache Problemumgehung:

"мария".mb_chars.capitalize.to_s # requires ActiveSupport::Multibyte

Andernfalls müssen Sie das Unicode- Juwel installieren und wie folgt verwenden:

require 'unicode'

Unicode::capitalize("мария") #=> Мария

Ruby 1.8:

Stellen Sie sicher, dass Sie den magischen Codierungskommentar verwenden :

#!/usr/bin/env ruby

puts "мария".capitalize

gibt invalid multibyte char (US-ASCII), während:

#!/usr/bin/env ruby
#coding: utf-8

puts "мария".capitalize

funktioniert fehlerfrei, aber auch im Abschnitt "Ruby 2.3 und niedriger" finden Sie Informationen zur tatsächlichen Großschreibung.

Alberto Santini
quelle
19
Beachten Sie, dass anscheinend erzeugt "my API is great".capitalizewird, My api is greatwas wahrscheinlich unerwünschtes Verhalten ist. Diese Antwort beantwortet die Frage also nicht wirklich, da er nur möchte, dass der ERSTE Buchstabe in Großbuchstaben und andere unberührt bleibt.
Daniel AR Werner
55

Großschreibung des ersten Buchstabens des ersten Wortes der Zeichenfolge

"kirk douglas".capitalize
#=> "Kirk douglas"

Großschreibung des ersten Buchstabens jedes Wortes

In Schienen:

"kirk douglas".titleize
=> "Kirk Douglas"

ODER

"kirk_douglas".titleize
=> "Kirk Douglas"    

In Rubin:

"kirk douglas".split(/ |\_|\-/).map(&:capitalize).join(" ") 
#=> "Kirk Douglas"

außerhalb von Schienen, aber immer noch die titleize-Methode verwenden wollen

require 'active_support/core_ext'
"kirk douglas".titleize #or capitalize
boulder_ruby
quelle
1
Upvote für eine reine Ruby-Lösung. Zu faul, um Rails richtig
illbzo1
19

Leider ist es für eine Maschine unmöglich, richtig auf- / abzusteigen / groß zu schreiben. Es braucht viel zu viele Kontextinformationen, als dass ein Computer sie verstehen könnte.

Aus diesem Grund unterstützt Rubys StringKlasse nur die Großschreibung von ASCII-Zeichen, da sie dort zumindest etwas genau definiert ist.

Was meine ich mit "Kontextinformationen"?

Um beispielsweise irichtig groß zu schreiben, müssen Sie wissen, in welcher Sprache der Text geschrieben ist. Englisch hat beispielsweise nur zwei is: Großbuchstaben Iohne Punkt und Klein imit einem Punkt. Aber Türkisch hat vier is: Kapital Iohne Punkt, Kapital İmit einem Punkt, klein ıohne Punkt, klein imit einem Punkt. Also auf Englisch 'i'.upcase # => 'I'und Türkisch 'i'.upcase # => 'İ'. Mit anderen Worten: Da 'i'.upcaseje nach Sprache zwei unterschiedliche Ergebnisse zurückgegeben werden können, ist es offensichtlich unmöglich, ein Wort richtig zu groß zu schreiben, ohne seine Sprache zu kennen.

Aber Ruby kennt die Sprache nicht, sondern nur die Kodierung. Daher ist es unmöglich, eine Zeichenfolge mit Rubys integrierter Funktionalität richtig zu aktivieren.

Es kommt noch schlimmer: Auch mit der Sprache zu kennen, ist es manchmal unmöglich ist Kapitalisierung richtig zu machen. Zum Beispiel auf Deutsch 'Maße'.upcase # => 'MASSE'( Maße ist der Plural von Maß, was Messung bedeutet ). Jedoch 'Masse'.upcase # => 'MASSE'(was Masse bedeutet ). Also, was ist 'MASSE'.capitalize? Mit anderen Worten: Für eine korrekte Großschreibung ist eine umfassende künstliche Intelligenz erforderlich.

Anstatt also manchmal die falsche Antwort zu geben, Rubin wählt manchmal keine Antwort geben überhaupt , weshalb nicht-ASCII - Zeichen einfach in downcase ignoriert get / upcase / Operationen nutzen. (Was natürlich auch zu falschen Ergebnissen führt, aber zumindest ist es leicht zu überprüfen.)

Jörg W Mittag
quelle
4
Entschuldigung, aber Ihre Argumentation hält kein Wasser. Es ist nicht wahr, dass Ruby sich dafür entscheidet, überhaupt keine Antwort zu geben, Ruby gibt immer eine Antwort, die oft falsch ist - zB "мария" .upcase sollte niemals "мария" zurückgeben, was in keinem Kontext korrekt ist. Und Ihre Abweichungen von der Notwendigkeit von KI sind überhaupt nicht relevant - nichts hindert ein Upcase daran, ein Array zu speichern, sagen Sie ['I', 'İ'] für 'i'.upcase, und lassen Sie den Anrufer entscheiden, welche Großschreibung relevant ist in einer bestimmten Situation. Derzeit ist der Umgang von Ruby mit der Konvertierung zwischen Groß- und Kleinbuchstaben fehlerhaft, und das war's.
Michau
2
-1 weil es eine Hauptstadt Eszett gibt . Die Verwendung eines nicht vollständig formalisierten Bereichs kann nicht als Beweis dafür dienen, dass diese Lösung nur mit AI möglich ist.
Mike
15

Nun, nur damit wir wissen, wie man nur den ersten Buchstaben großschreibt und den Rest in Ruhe lässt, denn manchmal ist es das, was gewünscht wird:

['NASA', 'MHz', 'sputnik'].collect do |word|
  letters = word.split('')
  letters.first.upcase!
  letters.join
end

 => ["NASA", "MHz", "Sputnik"]

Ein Anruf capitalizewürde dazu führen ["Nasa", "Mhz", "Sputnik"].

Huliax
quelle
Vielen Dank, genau das, wonach ich gesucht habe, nützlich, um Überschriften in 'Satzfall' umzuwandeln
Good Lux
2
word[0] = word[0].upcase
David
@David. NEIN! Dadurch werden die Werte der Wörter in dem Array geändert, für das #collect aufgerufen wird. Das ist eine schlimme Nebenwirkung.
Huliax
Ich zeigte einen einfacheren Weg, um den ersten Buchstaben eines Wortes groß zu schreiben, indem ich die inneren 3 Zeilen dieser Lösung ersetzte, was ich durch die Verwendung der wordVariablen deutlich machte. Wenn Sie mehr Wörter haben, rufen Sie sie einfach bei allen an! ;)words.map{|word| word[0] = word[0].upcase}
David
@David. Ihr Code beträgt #capitalize!und nicht #capitalize. Letzterer gibt einen neuen String zurück, während Ersterer den Empfänger der Methode ändert (in diesem Fall ist der Empfänger wordund die Methode ist #[]). Wenn Sie Ihren Code in einem # kollect-Block verwendet haben, erhalten Sie zwei verschiedene Arrays mit jeweils denselben String-Objekten (und die Strings wurden geändert). Das ist nichts, was Sie normalerweise tun möchten. Auch wenn Sie sich dessen bewusst sind, sollten andere Leser dies verstehen.
Huliax
8

Schienen 5+

Ab Active Support und Rails 5.0.0.beta4 können Sie eine der beiden Methoden verwenden: String#upcase_firstoder ActiveSupport::Inflector#upcase_first.

"my API is great".upcase_first #=> "My API is great"
"мария".upcase_first           #=> "Мария"
"мария".upcase_first           #=> "Мария"
"NASA".upcase_first            #=> "NASA"
"MHz".upcase_first             #=> "MHz"
"sputnik".upcase_first         #=> "Sputnik"

Weitere Informationen finden Sie unter " Rails 5: Neue upcase_first-Methode ".

user1519240
quelle
3

Verwenden Sie capitalize. Aus der String- Dokumentation:

Gibt eine Kopie von str zurück, wobei das erste Zeichen in Großbuchstaben und der Rest in Kleinbuchstaben konvertiert wird.

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"
jhwist
quelle
Verwenden Sie das Ausrufezeichen nur, wenn die ursprüngliche Zeichenfolge geändert werden soll.
Magnar
doh Danke, habe meinen Fehler behoben.
Jhwist
5
-1. Das OP erwähnt ausdrücklich deutschen und russischen Text, der Nicht-ASCII-Zeichen impliziert. String#upcase(und auch String#downcase) sind nur für ASCII-Zeichen definiert.
Jörg W Mittag
1
Die heutige Verwendung von Ruby 2.5.0 String#upcasescheint bei Nicht-ASCII-Zeichen einwandfrei zu funktionieren. 2.5.0 :001 > "мария".upcase => "МАРИЯ"
Huliax
1
@Huliax Wie in der akzeptierten Antwort erwähnt, war dies erst seit Ruby 2.4.0 (das 2016 veröffentlicht wurde) der Fall.
Nisetama
2

Sie können verwenden mb_chars. Dies respektiert Umlaute:

class String

  # Only capitalize first letter of a string
  def capitalize_first
    self[0] = self[0].mb_chars.upcase
    self
  end

end

Beispiel:

"ümlaute".capitalize_first
#=> "Ümlaute"
Schleim
quelle
0

Im Folgenden finden Sie eine weitere Möglichkeit, jedes Wort in einer Zeichenfolge groß zu schreiben. \wstimmt nicht mit kyrillischen oder lateinischen Zeichen mit diakritischen Zeichen überein, [[:word:]]tut es aber . upcase, downcase, capitalize, Und swapcasegalt nicht für Nicht-ASCII - Zeichen , bis Ruby - 2.4.0 , die im Jahr 2016 veröffentlicht wurde.

"aAa-BBB ä мария _a a_a".gsub(/\w+/,&:capitalize)
=> "Aaa-Bbb ä мария _a A_a"
"aAa-BBB ä мария _a a_a".gsub(/[[:word:]]+/,&:capitalize)
=> "Aaa-Bbb Ä Мария _a A_a"

[[:word:]] stimmt mit Zeichen in diesen Kategorien überein:

Ll (Letter, Lowercase)
Lu (Letter, Uppercase)
Lt (Letter, Titlecase)
Lo (Letter, Other)
Lm (Letter, Modifier)
Nd (Number, Decimal Digit)
Pc (Punctuation, Connector)

[[:word:]]stimmt mit allen 10 Zeichen in der PcKategorie "Interpunktion, Konnektor" ( ) überein :

005F _ LOW LINE
203F ‿ UNDERTIE
2040 ⁀ CHARACTER TIE
2054 ⁔ INVERTED UNDERTIE
FE33 ︳ PRESENTATION FORM FOR VERTICAL LOW LINE
FE34 ︴ PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
FE4D ﹍ DASHED LOW LINE
FE4E ﹎ CENTRELINE LOW LINE
FE4F ﹏ WAVY LOW LINE
FF3F _ FULLWIDTH LOW LINE

Dies ist eine weitere Möglichkeit, nur das erste Zeichen einer Zeichenfolge in Großbuchstaben umzuwandeln:

"striNG".sub(/./,&:upcase)
=> "StriNG"
Nisetama
quelle