2013-08-01 20 views
28

Come faccio assetto di partenza e carattere finale di una stringa in ScalaTaglio stringhe in Scala

Se l'ingresso è

,hello (or) hello, 

ho bisogno l'uscita come ciao

C'è c'è qualche metodo integrato per farlo in Scala?

risposta

63

Prova

val str = " foo " 
str.trim 

e dare un'occhiata a the documentation. Se avete bisogno di sbarazzarsi del carattere ,, troppo, si potrebbe provare qualcosa di simile:

str.stripPrefix(",").stripSuffix(",").trim 

Un altro modo per ripulire il front-end della stringa sarebbe

val ignoreable = ", \t\r\n" 
str.dropWhile(c => ignorable.indexOf(c) >= 0) 

che sarebbe anche prendersi cura di stringhe come ",,, ,,hello"

E per buona misura, ecco una funzione molto piccolo, che fa tutto in un sol colpo da sinistra a destra attraverso la stringa:

def stripAll(s: String, bad: String): String = { 

    @scala.annotation.tailrec def start(n: Int): String = 
     if (n == s.length) "" 
     else if (bad.indexOf(s.charAt(n)) < 0) end(n, s.length) 
     else start(1 + n) 

    @scala.annotation.tailrec def end(a: Int, n: Int): String = 
     if (n <= a) s.substring(a, n) 
     else if (bad.indexOf(s.charAt(n - 1)) < 0) s.substring(a, n) 
     else end(a, n - 1) 

    start(0) 
} 

Usa come

stripAll(stringToCleanUp, charactersToRemove) 

ad esempio,

stripAll(" , , , hello , ,,,, ", " ,") => "hello" 
+0

@Dirk: sei sicuro che la magia di 'tailrec' non possa essere sostituita con un semplice codice di regexp? Inoltre, 'ignorabile contiene c' potrebbe essere considerato più leggibile. –

+0

@ErikAllik: Sono abbastanza sicuro, che tutto questo avrebbe potuto essere realizzato con un'espressione regolare (almeno in questo caso). Inoltre: provenendo da Scheme, in realtà mi trovo a ricorrere molto alla ricorsione in coda; Penso che sia una questione di abitudine più che altro. L'annotazione 'tailrec' fa in modo che il compilatore mi dia un errore, se non può riscrivere il codice in loop semplici. Trovo che sia utile, data la mia predisposizione all'utilizzo della ricorsione di coda e alle limitazioni della VM Java per supportarle correttamente attraverso le (ad esempio) chiamate di funzione. – Dirk

+0

BTW, 'trim' non è molto documentato nel collegamento della documentazione fornito. Avresti bisogno di qualche solido scavo di scala letterale (o solo sperimentazione) per arrivare a quello che fa. – matanster

8

Per tagliare l'inizio e il carattere che termina in una stringa, utilizzare un mix di drop e dropRight:

scala> " ciao, ". drop (1) .dropRight (1)

res4: String = ciao

La chiamata di rilascio rimuove il primo carattere, dropRight rimuove l'ultimo. Si noti che questo non è "intelligente" come il trim è. Se non hai caratteri extra all'inizio di "ciao", lo taglierai a "ciao". Se hai bisogno di qualcosa di più complicato, la sostituzione regex è probabilmente la risposta.

+0

Si prega di fornire un motivo per il downvote. Questa è una soluzione perfettamente accettabile alla domanda "sottostringa" – lreeder

+0

lancia java.lang.StringIndexOutOfBoundsException quindi è necessario "if" prima di usarlo, non troppo alla scala –

+1

@CC, grazie per le critiche costruttive. Sono d'accordo sul fatto che usare "if" è goffo e aggiornare la mia risposta per sostituire la sottostringa con drop() che dovrebbe realizzare la stessa cosa senza il rischio di Eccezione – lreeder

7

Se si vuole tagliare solo le virgole e potrebbe avere più di una su entrambe le estremità, si potrebbe fare questo:

str.dropWhile(_ == ',').reverse.dropWhile(_ == ',').reverse 

L'uso di reverse qui è perché non c'è dropRightWhile.

Se stai guardando una singola virgola possibile, stripPrefix e stripSuffix sono la strada da percorrere, come indicato da Dirk.

0

Dato desideri solo per tagliare i caratteri non validi dal prefisso e la suffisso di una determinata stringa (non eseguire la scansione attraverso l'intera stringa), ecco una piccola trimPrefixSuffixChars funzione per eseguire rapidamente il desiderato effetto:

def trimPrefixSuffixChars(
    string: String 
    , invalidCharsFunction: (Char) => Boolean = (c) => c == ' ' 
): String = 
    if (string.nonEmpty) 
    string 
     .dropWhile(char => invalidCharsFunction(char)) //trim prefix 
     .reverse 
     .dropWhile(char => invalidCharsFunction(char)) //trim suffix 
     .reverse 
    else 
    string 

Questa funzione fornisce un valore predefinito per la invalidCharsFunction definire solo lo spazio di caratteri (" ") come non valido. Ecco cosa la conversione sarebbe simile per le seguenti stringhe di input:

trimPrefixSuffixChars(" Tx ")  //returns "Tx" 
trimPrefixSuffixChars(" . Tx . ") //returns ". Tx ." 
trimPrefixSuffixChars(" T x ") //returns "T x" 
trimPrefixSuffixChars(" . T x . ") //returns ". T x ." 

Se si dispone si preferisce specificare la propria funzione invalidCharsFunction, poi passarlo nella chiamata in questo modo:

trimPrefixSuffixChars(",Tx. ", (c) => !c.isLetterOrDigit)  //returns "Tx" 
trimPrefixSuffixChars(" ! Tx # ", (c) => !c.isLetterOrDigit) //returns "Tx" 
trimPrefixSuffixChars(",T x. ", (c) => !c.isLetterOrDigit) //returns "T x" 
trimPrefixSuffixChars(" ! T x # ", (c) => !c.isLetterOrDigit) //returns "T x" 

Questo tenta di semplificare un numero delle soluzioni di esempio fornite in altre risposte.

0

Qualcuno ha richiesto una regex-versione, che sarebbe qualcosa di simile:

val trim: Regex = raw"[,\s]*(|.*[^,\s])[,\s]*".r 

val result = " , ,, hello, ,," match { case trim(x) => x } 

risultato è: result: String = hello

Lo svantaggio con regex (non solo in questo caso, ma sempre), è che è piuttosto difficile da leggere per qualcuno che non ha già familiarità con la sintassi. Il codice è bello e conciso, però.

Problemi correlati