Come scrivere in maiuscolo la prima lettera in una stringa in Ruby


134

Il upcasemetodo utilizza le maiuscole per l'intera stringa, ma è necessario utilizzare solo la prima lettera maiuscola.

Inoltre, devo supportare diverse lingue popolari, come il tedesco e il russo.

Come lo faccio?


4
Ricorda che alcune lingue hanno idee diverse su quale sia la prima lettera maiuscola. In irlandese, fai cose come "i mBaile Átha Cliath" ("a Dublino") - lettere minuscole "m", lettere maiuscole "B". (Vedi en.wikipedia.org/wiki/Consonant_mutation#Celtic_languages se sei curioso di sapere perché gli irlandesi lo farebbero e perché abbia un senso.)
James Moore,

3
Inoltre, tieni presente che #capitalize ridimensionerà tutte le lettere che non sono la prima lettera ... che non è sempre ciò che desideri. ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Huliax,

Risposte:


260

Dipende dalla versione di Ruby che usi:

Ruby 2.4 e versioni successive:

Funziona semplicemente, poiché Ruby v2.4.0 supporta il case mapping Unicode:

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

Ruby 2.3 e precedenti:

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

Il problema è che semplicemente non fa quello che vuoi, ma produce марияinvece Мария.

Se stai usando Rails c'è una soluzione semplice:

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

Altrimenti, dovrai installare la gemma unicode e usarla in questo modo:

require 'unicode'

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

Ruby 1.8:

Assicurati di utilizzare il commento magico di codifica :

#!/usr/bin/env ruby

puts "мария".capitalize

invalid multibyte char (US-ASCII), mentre:

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

puts "мария".capitalize

funziona senza errori, ma vedi anche la sezione "Ruby 2.3 e versioni precedenti" per la vera capitalizzazione.


19
Si noti che apparentemente "my API is great".capitalizeprodurrà un My api is greatcomportamento probabilmente indesiderato. Quindi questa risposta in realtà non risponde alla domanda poiché vuole solo la PRIMA lettera trasformata in maiuscolo e gli altri intatti.
Daniel AR Werner,

55

scrivere in maiuscolo la prima lettera della prima parola della stringa

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

scrivere in maiuscolo la prima lettera di ogni parola

In rotaie:

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

O

"kirk_douglas".titleize
=> "Kirk Douglas"    

In rubino:

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

al di fuori delle rotaie, ma desidera comunque utilizzare il metodo titleize

require 'active_support/core_ext'
"kirk douglas".titleize #or capitalize

1
Promuovi una soluzione Ruby pura. Troppo pigro per accendere Rails nel modo giusto, e questo ha fatto il trucco :)
illbzo1

19

Sfortunatamente, è impossibile per una macchina eseguire l'upcase / downcase / capitalizzazione corretta. Ha bisogno di troppe informazioni contestuali per un computer per capire.

Ecco perché la Stringclasse di Ruby supporta solo le maiuscole per i caratteri ASCII, perché è almeno un po ' ben definita.

Cosa intendo per "informazioni contestuali"?

Ad esempio, per capitalizzare icorrettamente, devi sapere in quale lingua è il testo. L'inglese, ad esempio, ha solo due is: maiuscolo Isenza punto e piccolo icon un punto. Ma il turco ha quattro is: maiuscolo Isenza punto, maiuscolo İcon punto, piccolo ısenza punto, piccolo icon punto. Quindi, in inglese 'i'.upcase # => 'I'e in turco'i'.upcase # => 'İ' . In altre parole: poiché 'i'.upcasepuò restituire due risultati diversi, a seconda della lingua, è ovviamente impossibile capitalizzare correttamente una parola senza conoscerne la lingua.

Ma Ruby non conosce la lingua, conosce solo la codifica. Pertanto è impossibile capitalizzare correttamente una stringa con la funzionalità integrata di Ruby.

Peggio ancora: anche con la conoscenza della lingua, a volte è impossibile fare correttamente le maiuscole. Ad esempio, in tedesco 'Maße'.upcase # => 'MASSE'( Maße è il plurale di Maß che significa misurazione ). Tuttavia, 'Masse'.upcase # => 'MASSE'(che significa massa ). Allora, cos'è 'MASSE'.capitalize? In altre parole: la corretta capitalizzazione richiede un'intelligenza artificiale completa.

Così, invece di dare a volte la risposta sbagliata, Rubino sceglie di volte danno nessuna risposta a tutti , motivo per cui i caratteri non ASCII ottenere semplicemente ignorate in downcase / upcase / capitalizzare le operazioni. (Che ovviamente legge anche risultati errati, ma almeno è facile da controllare.)


4
Mi dispiace, ma la tua argomentazione non regge. Non è vero che Ruby sceglie di non dare affatto una risposta, Ruby dà sempre una risposta, che spesso è sbagliata - ad esempio "мария" .upcase non dovrebbe mai restituire "мария", che non è corretto in nessun contesto. E le tue divagazioni sulla necessità dell'IA non sono affatto rilevanti: non c'è nulla che impedisca di riqualificare un array in upcase, dire ['I', 'İ'] per 'i'.case e lasciare che il chiamante decida quale maiuscola è rilevante in una data situazione. Attualmente la gestione di Ruby della conversione tra lettere maiuscole e minuscole è interrotta, e basta.
Michau,

2
-1 perché c'è una capitale Eszett . L'uso di un'area non completamente formalizzata non può servire come prova di tale soluzione è possibile solo con l'IA.
Mike,

15

Bene, solo così sappiamo come mettere in maiuscolo solo la prima lettera e lasciare il resto da soli, perché a volte è quello che si desidera:

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

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

La chiamata capitalizecomporterebbe ["Nasa", "Mhz", "Sputnik"].


Grazie proprio quello che stavo cercando, utile per convertire le intestazioni in "caso di condanna"
Good Lux

2
word[0] = word[0].upcase
David,

@ David. NO! Ciò modifica i valori delle parole nell'array su cui viene chiamato #collect. Questo è un brutto effetto collaterale.
Huliax,

Stavo mostrando un modo più semplice per scrivere in maiuscolo la prima lettera di una parola, sostituendo le 3 linee interne di questa soluzione, che ho chiarito usando la wordvariabile. Certo, se hai più parole, chiamale su tutte! ;)words.map{|word| word[0] = word[0].upcase}
David

@ David. Il tuo codice equivale a #capitalize!e non #capitalize. Il secondo restituisce una nuova stringa mentre il primo modifica il destinatario del metodo (in questo caso il ricevitore è worde il metodo è #[]). Se usassi il tuo codice all'interno di un blocco #collect, finiresti con due matrici diverse con gli stessi oggetti String in ciascuno di essi (e le stringhe sarebbero state modificate). Non è qualcosa che normalmente vorresti fare. Anche se ne sei consapevole, altri lettori dovrebbero capirlo.
Huliax,

8

Rotaie 5+

A partire da Active Support e Rails 5.0.0.beta4 è possibile utilizzare uno di entrambi i metodi: String#upcase_firsto 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"

Controlla " Rails 5: New upcase_first Method " per maggiori informazioni.


3

Usa capitalize. Dalla documentazione di String :

Restituisce una copia di str con il primo carattere convertito in maiuscolo e il resto in minuscolo.

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"

Utilizzare il punto esclamativo solo se si desidera modificare la stringa originale.
Magnar,

doh Grazie, risolto il mio errore.
jhwist,

5
-1. L'OP menziona esplicitamente il testo tedesco e russo, che implica caratteri non ASCII. String#upcase(e anche String#downcase) sono definiti solo per caratteri ASCII.
Jörg W Mittag,

1
Usando Ruby 2.5.0 oggi e String#upcasesembra funzionare bene su caratteri non ASCII. 2.5.0 :001 > "мария".upcase => "МАРИЯ"
Huliax,

1
@Huliax Come menzionato nella risposta accettata, questo è stato solo dopo Ruby 2.4.0 (che è stato rilasciato nel 2016).
nisetama,

2

È possibile utilizzare mb_chars. Questo rispetta umlaute:

class String

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

end

Esempio:

"ümlaute".capitalize_first
#=> "Ümlaute"

0

Di seguito è riportato un altro modo per scrivere in maiuscolo ogni parola in una stringa. \wnon corrisponde a caratteri cirillici o latini con segni diacritici ma lo [[:word:]]fa. upcase, downcase, capitalize, E swapcasenon si applica ai caratteri non-ASCII fino Rubino 2.4.0 che è stato rilasciato nel 2016.

"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:]] corrisponde ai personaggi in queste categorie:

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

[[:word:]]corrisponde a tutti e 10 i caratteri nella categoria "Punteggiatura, connettore" ( Pc):

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

Questo è un altro modo per convertire in maiuscolo solo il primo carattere di una stringa:

"striNG".sub(/./,&:upcase)
=> "StriNG"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.