Mettere in maiuscolo solo il primo carattere della stringa e lasciare gli altri in pace? (Rails)


102

Sto cercando di convincere Rails a scrivere in maiuscolo il primo carattere di una stringa e lasciare tutti gli altri come sono. Sto riscontrando un problema in cui "vengo da New York" viene trasformato in "vengo da New York".

Quale metodo dovrei usare per selezionare il primo carattere?

Grazie

EDIT: Ho provato a implementare ciò che macek ha suggerito, ma ricevo un errore di "metodo non definito" capitalizza " . Il codice funziona correttamente senza la riga in maiuscolo. Grazie per l'aiuto!

def fixlistname!
  self.title = self.title.lstrip + (title.ends_with?("...") ? "" : "...")
  self.title[0] = self.title[0].capitalize
  errors.add_to_base("Title must start with \"You know you...\"") unless self.title.starts_with? 'You know you'
end

EDIT 2: funziona. Grazie per l'aiuto!

EDIT 3: Aspetta, no, non l'ho fatto ... Ecco cosa ho nel mio modello di lista.

def fixlistname!
  self.title = self.title.lstrip + (title.ends_with?("...") ? "" : "...")
  self.title.slice(0,1).capitalize + self.title.slice(1..-1)
  errors.add_to_base("Title must start with \"You know you...\"") unless self.title.starts_with?  'You know you'
end

MODIFICA 4: Ho provato la modifica di macek e ricevo ancora un errore di "capitalizzazione" del metodo non definito . Cosa potrei fare di sbagliato?

def fixlistname!
  self.title = title.lstrip
  self.title += '...' unless title.ends_with?('...')
  self.title[0] = title[0].capitalize
  errors.add_to_base('Title must start with "You know you..."') unless title.starts_with?("You know you")
end

EDIT 5: questo è strano. Sono in grado di eliminare l'errore del metodo non definito utilizzando la riga seguente. Il problema è che sembra sostituire la prima lettera con un numero. Ad esempio, invece di mettere in maiuscolo la y in You , trasforma la y in un 121

self.title[0] = title[0].to_s.capitalize

In base a EDIT 3, devi iniziare la riga 2 con self.title = . Inoltre, su tutte e 3 le righe, è necessario solo self.titlea sinistra di un =(segno di uguale). In altri posti puoi semplicemente usare title. Vedi la modifica sulla mia risposta per un esempio.
maček

2
Il problema in Edit4 è che hai solo un carattere - non più una stringa - quindi non riconoscerà la funzione stringa "capitalize".
Taryn East

Il problema con la modifica 5 è che il titolo [0] è un numero fisso, quindi chiamare titolo [0] .to_s ti darà solo il numero del carattere (cioè 121 come stringa: "121"). Puoi fare self.title [0] = title.first.capitalize se vuoi!
Nick

Ho aggiunto un #upcase_first_case e ho effettuato una richiesta pull: github.com/rails/rails/pull/15319 . Sentiti libero di aggiungere il tuo feedback lì.
Aldo 'xoen' Giambelluca

Risposte:


93

Titleize renderà maiuscola ogni parola. Questa riga sembra pesante, ma garantirà che l'unica lettera modificata sia la prima.

new_string = string.slice(0,1).capitalize + string.slice(1..-1)

Aggiornare:

irb(main):001:0> string = "i'm from New York..."
=> "i'm from New York..."
irb(main):002:0> new_string = string.slice(0,1).capitalize + string.slice(1..-1)
=> "I'm from New York..."

Aspetta, ancora non funziona. Falso allarme: / Penso che lo sto solo implementando in modo sbagliato.
Daniel O'Connor

1
Daniel - è generalmente una buona forma "accettare" una risposta che ha risolto il tuo problema. Puoi farlo facendo clic sul "segno di spunta" a sinistra della risposta. :)
Taryn East

1
Ho frainteso la domanda, altrimenti volevo darti un 1 in più. Stavo cercando .titleize invece di .capitalize. Grazie comunque Taryn!
Eric Wanchic

OOC - Perché questo ti impedisce di dare un voto positivo? Ho risposto correttamente alla domanda del poster originale? Se la pensi così, allora dai un voto positivo. Non deve dipendere da nient'altro ... :)
Taryn East,

2
Quindi, eccolo: s[0].capitalize + s[1..-1] if s.present?
Alex Escalante

126

Questo dovrebbe farlo:

title = "test test"     
title[0] = title[0].capitalize
puts title # "Test test"

40
O più concisamente,title[0] = title[0].capitalize
Jon Garvin

Questa è una soluzione molto elegante.
Karew

1
@ JonGarvin title [0] .capitalize non funziona (almeno con Ruby 1.8.7), poiché title [0] restituisce un Fixnum e capitalize si aspetta una stringa .. quindi penso che title.first.capitalize sia il modo per partire.
Nick

2
peccato che non puoititle.first.capitalize!
Adam Waite

1
capitalizeconverte tutte le lettere dopo la prima lettera in minuscolo, quindi non funziona per la stringa presentata nella domanda ("sono di New York").
Mark Schneider

57

Puoi usare umanizza. Se non hai bisogno di trattini bassi o altre maiuscole nelle righe di testo.

Ingresso:

"i'm from New_York...".humanize

Produzione:

"I'm from new york..."

7
L'OP voleva specificamente evitare "new york"
phatmann

Hmm davvero, un po 'troppo velocemente con la mia risposta.
Bartuzz

17
@Bartuzz Anche se questo non è quello che voleva OP, questo è esattamente quello che stavo cercando. Grazie!
Yetti

new york tuttavia sarebbe sgrammaticato come nome proprio e dovrebbe usare le maiuscole.
Shayne

Attenzione, humanizeè Rails, esattamente il metodo ActiveSupport. Il rubino normale non può farlo.
Penguin

51
str = "this is a Test"
str.sub(/^./, &:upcase)
# => "This is a Test"

1
Conciso ed elegante. Credo che questa dovrebbe essere la risposta migliore.
Chris

Sono d'accordo. Penso che questa dovrebbe essere la risposta accettata.
Garry Pettet

Una stranezza è che dal ^significa che l'inizio della riga, "\nfoo"diventa "\nFoo". Probabilmente va bene per la maggior parte dei casi d'uso. Dal momento che è a sube non a gsub, sarà comunque solo upcase una lettera, anche con stringhe multilinea.
Henrik N

È possibile ottenere la limitazione di cui sopra utilizzando str.sub(/\S/, &:upcase), che troverà il primo carattere non di spazio bianco e lo sostituirà.
Anthony Panozzo

39

A partire da Rails 5.0.0.beta4 puoi usare il nuovo String#upcase_firstmetodo o ActiveSupport::Inflector#upcase_firstfarlo. Controlla questo post del blog per maggiori informazioni.


Questa è una fantastica notizia! Stavo pensando a cosa possiamo fare adesso e forse un polyfill per Rails 4 sarebbe carino.
hakunin

Nota che upcase_first e non gestisce accenti / caratteri speciali, anche con mb_chars
user3033467

14

Una soluzione orientata agli oggetti:

class String
  def capitalize_first_char
    self.sub(/^(.)/) { $1.capitalize }
  end
end

Quindi puoi semplicemente fare questo:

"i'm from New York".capitalize_first_char

Almeno qualcuno ha scritto una soluzione elegante con l'estensione della Stringclasse.
Dmitriy

@Dmitriy perché la scimmia rattoppa la classe delle corde elegante?
Gerard Simpson


6

Modifica 2

Non riesco a replicare il tuo problema. Vai avanti ed esegui questo script Ruby nativo. Genera l'output esatto che stai cercando e Rails supporta tutti questi metodi. Con che tipo di input hai problemi?

#!/usr/bin/ruby
def fixlistname(title)
  title = title.lstrip
  title += '...' unless title =~ /\.{3}$/
  title[0] = title[0].capitalize
  raise 'Title must start with "You know you..."' unless title =~ /^You know you/
  title
end

DATA.each do |title|
  puts fixlistname(title)
end

__END__
you know you something WITH dots ...
you know you something WITHOUT the dots
  you know you something with LEADING whitespace...
  you know you something with whitespace BUT NO DOTS
this generates error because it doesn't start with you know you

produzione

You know you something WITH dots ...
You know you something WITHOUT the dots...
You know you something with LEADING whitespace...
You know you something with whitespace BUT NO DOTS...
RuntimeError: Title must start with "You know you..."

modificare

In base alla tua modifica, puoi provare qualcosa di simile.

def fixlistname!
  self.title = title.lstrip
  self.title += '...' unless title.ends_with?('...')
  self.title[0] = title[0].capitalize
  errors.add_to_base('Title must start with "You know you..."') unless title.starts_with?("You know you")
end

Originale

Questo farà il trucco

s = "i'm from New York"
s[0] = s[0].capitalize
#=> I'm from New York

Quando cercavi di usare String#capitalizesu tutta la stringa, vedevi I'm from new yorkperché il metodo:

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"

+1 perché non pensavo che avrebbe funzionato finché non l'ho provato sul mio pc :)
Jeriko

Ciao, grazie per l'aiuto. Ma cosa sto facendo di sbagliato? Ho modificato la domanda originale per includere il mio codice.
Daniel O'Connor

Ho usato il suggerimento di Taryn e l'ho fatto funzionare. Grazie per l'aiuto però!
Daniel O'Connor

Ciao, stackoverflow dice che hai apportato una modifica, ma non vedo nulla di diverso?
Daniel O'Connor

6
my_string = "hello, World"
my_string.sub(/\S/, &:upcase) # => "Hello, World"

Non fallisce se my_string è vuoto! Bello. Questo è ciò di cui ho bisogno.
Huliax

4

La maggior parte di queste risposte modifica la stringa in posizione, quando stai solo formattando per visualizzare l'output potresti non voler cambiare la stringa sottostante in modo da poterla usare tapdopo a dupper ottenere una copia modificata

'test'.dup.tap { |string| string[0] = string[0].upcase }

3

Se e solo se OP volesse eseguire patch di scimmia sull'oggetto String, allora questo può essere usato

class String
  # Only capitalize first letter of a string
  def capitalize_first
    self.sub(/\S/, &:upcase)
  end
end

Ora usalo:

"i live in New York".capitalize_first #=> I live in New York

2

Una versione ancora più breve potrebbe essere:

s = "i'm from New York..."
s[0] = s.capitalize[0]

2

Nessuno ha menzionato gsub, il che ti consente di farlo in modo conciso.

string.gsub(/^([a-z])/) { $1.capitalize }

Esempio:

 > 'caps lock must go'.gsub(/^(.)/) { $1.capitalize }
=> "Caps lock must go"

1

Forse il modo più semplice.

s = "test string"
s[0] = s[0].upcase
# => "Test string"

1

Nota che se devi gestire caratteri multibyte, cioè se devi internazionalizzare il tuo sito, la s[0] = ...soluzione non sarà adeguata. Questa domanda su Stack Overflow suggerisce di utilizzare la gemma unicode-util

Ruby 1.9: come posso eseguire correttamente upcase e downcase di stringhe multibyte?

MODIFICARE

In realtà un modo più semplice per evitare almeno strane codifiche di stringhe è usare semplicemente String # mb_chars :

s = s.mb_chars
s[0] = s.first.upcase
s.to_s

0

Che dire del metodo di classificazione su stringa?

'somESTRIng'.classify

produzione:

#rails => 'SomESTRIng'

1
Sta facendo molte cose aggiuntive, come singolarizzare le parole. "hello worlds".classify # => "Hello world"
Pavel Pravosud

-3
string = "i'm from New York"
string.split(/\s+/).each{ |word,i| word.capitalize! unless i > 0 }.join(' ')
# => I'm from New York

Così sembra. Sono nuovo a ruby ​​e le altre risposte non hanno effettivamente fatto ciò che l'OP ha chiesto, quindi l'ho fatto funzionare: D Correggimi se sbaglio, ma AFAIK la modifica di una stringa cambiando stringa [i] non lo fa lavorare in molte lingue?
Jeriko

3
questa è una domanda specifica di Ruby. Non importa se string[i]non funziona in altre lingue. Aiutaci a mantenere StackOverflow libero da questo tipo di risposte compromesse. Non possiamo dire RTFM, ma anche una rapida occhiata ai Stringdocumenti avrebbe aiutato a evitare una risposta come questa ...
maček
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.