2012-11-28 9 views
8

Se ho la frase "New York City" come ottengo la prima lettera di ogni parola? Il mio googling mi ha solo mostrato come capitalizzare la prima lettera in ogni parola, che è apparentemente diversa da quello che sto cercando di fare.Come ottengo la prima lettera in ogni parola in scala?

Data la mia conoscenza limitata di Scala, potrei probabilmente farlo in modo procedurale, ma speravo che qualcuno potesse diffondere qualche conoscenza di Scala su di me e mostrarmi un esempio che descrive un approccio funzionale a questo problema.

risposta

24

Tutte le altre versioni funzionano bene, ma al fine di evitare il fallimento con le stringhe mal formattati (due spazi vuoti in una riga, stringa vuota), utilizzare

"New York City".split(" ").flatMap(_.headOption).mkString 

che funziona anche per

"New York City".split(" ").flatMap(_.headOption).mkString 

o anche

"".split(" ").flatMap(_.headOption).mkString 

Come suggerito da dhg, si potrebbe desiderare di usare una regex più appropriata come "\\s+" pure. Ma allora si potrebbe altrettanto bene usare qualcosa di ancora più appropriato:

"""\w+""".r.findAllIn("New York City").map(_.head).mkString 

(Qui il /\w+/ dovrebbe auspicabilmente ci risparmi da casi patologici in modo che possiamo andare con la versione .head.)

+3

' "New York City" .split ("\\ s +"). Mappa (_. Testa).mkString' realizza lo stesso obiettivo senza l'opzione '. – dhg

+2

@dhg ... ma non riesce sulla stringa vuota. – Debilski

+0

puoi filtrare i risultati vuoti, mantenendo solo quelli validi, che ti permetteranno di usare il metodo '_.head':' "New York City" .split ("") .filterNot (_. IsEmpty) .map (_ .head) .mkString' –

13
scala> "New York City".split(" ").map(_.head).mkString 
res5: String = NYC 

Questo si divide per "" in una matrice di parole. Quindi mappiamo su quell'array e chiamiamo String.head che ottiene il primo carattere.

5
"New York City".split(" ").toList.map(_(0)) 

dà i personaggi:

List[Char] = List(N, Y, C) 

Se si desidera utilizzare una stringa mkString sul List[Char]:

"New York City".split(" ").toList.map(_(0)) mkString 

per ottenere:

String = NYC 
4
"New York City".split(" ").map(_.charAt(0)) 

vi darà un array di caratteri

2

Ecco un'alternativa alla usando split (Regex).

Il trucco consiste nell'utilizzare zip per consentire il test del carattere corrente e precedente nella stessa iterazione mentre si attraversa la stringa, i limiti di parola sono costituiti da qualsiasi lettera preceduta da una non lettera.

I due casi speciali, la prima e l'ultima lettera, vengono gestiti da 1) anteponendo uno spazio a una copia della stringa che imposta anche l'inclinazione di 1 carattere richiesta per lo zip e 2) zip tronca le coppie parziali.

val s = "\n1New\n\t \t \tYork --City\n\t" 


def firstLetters(s: String) = { 
    " "+s zip s collect {case (w, c) if ! w.isLetter && c.isLetter => c} 
} 

firstLetters(s) 

rendimenti

Vector(N, Y, C) 
Problemi correlati