2011-10-12 13 views
8

ho bisogno di tagliare una stringa in Java in modo che:String trim in Java, mentre conserva piena parola

Il quick brown fox salta sul cane laz.

diventa

La rapida marrone ...

Nell'esempio di cui sopra, mi sto taglio a 12 caratteri. Se mi basta usare sottostringa vorrei avere:

La rapida br ...

Ho già un metodo per fare questo usando stringa, ma volevo sapere che cosa è il più veloce (più efficiente) modo di farlo perché una pagina potrebbe avere molte operazioni di taglio.

L'unico modo che posso pensare fuori è quello di dividere la stringa su spazi e rimetterlo insieme fino a quando la sua lunghezza passa la lunghezza del dato. C'è un altro modo? Forse un modo più efficiente in cui posso usare lo stesso metodo per fare un trim "soft" dove conservo l'ultima parola (come mostrato nell'esempio sopra) e un hard trim che è praticamente una sottostringa.

Grazie,

risposta

11

Di seguito è riportato un metodo che utilizzo per tagliare le stringhe lunghe nelle mie applicazioni web. Il "soft" boolean come si inserisce, se impostato su true manterrà l'ultima parola. Questo è il modo più conciso di farlo che potrei inventare che utilizza un StringBuffer che è molto più efficiente di ricreare una stringa che è immutabile.

public static String trimString(String string, int length, boolean soft) { 
    if(string == null || string.trim().isEmpty()){ 
     return string; 
    } 

    StringBuffer sb = new StringBuffer(string); 
    int actualLength = length - 3; 
    if(sb.length() > actualLength){ 
     // -3 because we add 3 dots at the end. Returned string length has to be length including the dots. 
     if(!soft) 
      return escapeHtml(sb.insert(actualLength, "...").substring(0, actualLength+3)); 
     else { 
      int endIndex = sb.indexOf(" ",actualLength); 
      return escapeHtml(sb.insert(endIndex,"...").substring(0, endIndex+3)); 
     } 
    } 
    return string; 
} 

Aggiornamento

ho cambiato il codice in modo che il ... è allegato in StringBuffer, questo per evitare inutili creazioni di String implicitamente che è lento e dispendioso.

Nota:escapeHtml è un'importazione statica da Commons apache:

import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;

è possibile rimuoverlo e il codice dovrebbe funzionare lo stesso.

+0

Come 'StringBuffer' aiuta le prestazioni qui? Non c'è alcun motivo per cui 'sottostringa',' indexOf' e 'length' sarebbero più veloci su' StringBuffer' che su 'String'. –

+0

Mi permetta di chiarire, il richiedente ha detto che era tokenizing e quindi rimettere insieme la stringa. Ogni volta che aggiunge un nuovo token alla stringa, l'intera stringa viene distrutta e ricreata. Per le stringhe lunghe questa operazione è molto più costosa dell'uso di un 'StringBuffer'. Anche se sono d'accordo, la differenza di prestazioni è probabilmente trascurabile considerando che il 'StringBuffer' è stato creato e quando torniamo creiamo effettivamente una stringa almeno 3 volte (sottostringa, punti di aggiunta, escape [, trim]). – Ali

+1

Il problema è che nel tuo codice non stai aggiungendo nulla a 'StringBuffer'. –

0

Effettua una ricerca per l'ultima occorrenza di uno spazio che è in una posizione meno o più di 11 e tagliare la corda lì, con l'aggiunta di "...".

0

Le vostre esigenze non sono chiare. Se hai problemi a articolarli in un linguaggio naturale, non sorprende che saranno difficili da tradurre in un linguaggio informatico come Java.

"preservare l'ultima parola" implica che l'algoritmo sanno cosa sia un "parola" è, quindi dovrete per dirgli che prima. La divisione è un modo per farlo. Uno scanner/parser con una grammatica è un altro.

Mi preoccuperei di farlo funzionare prima di preoccuparmi dell'efficienza.Fatelo funzionare, misuratelo e poi vedete cosa potete fare riguardo alle prestazioni. Tutto il resto è speculazione senza dati.

+0

Abbastanza giusto. Cosa intendevo per "preservare l'ultima parola" è che non voglio troncare una stringa su nessun carattere tranne uno spazio bianco? Ha senso? – AMZFR

0

ne dite:

mystring = mystring.replaceAll("^(.{12}.*?)\b.*$", "$1..."); 
+0

Puoi spiegare la regex? Questo preserverebbe l'ultima parola o no? La tua espressione regolare è diversa da quella di Bohemian. – AMZFR

+0

Prendere i primi 12 caratteri e il minimo dopo di ciò per completare la parola e aggiungere ... –

+0

In realtà ho dimenticato di aggiungere qualcosa alla fine del modello per rimuovere il resto della stringa. Modifica ora per risolvere. –

7

Ecco un semplice, regex-based, soluzione di 1-line:

str.replaceAll("(?<=.{12})\\b.*", "..."); // How easy was that!? :) 

Spiegazione:

  • (?<=.{12}) è uno sguardo negativo dietro, che afferma che ci sono almeno 12 caratteri a sinistra della partita, ma è un non-cattura (cioè zero larghezza) partita
  • \b.* corrisponde al primo confine di parola (dopo almeno 12 caratteri - sopra) fino alla fine

Questo viene sostituito con "..."

Ecco un test:

public static void main(String[] args) { 
    String input = "The quick brown fox jumps over the lazy dog."; 
    String trimmed = input.replaceAll("(?<=.{12})\\b.*", "..."); 
    System.out.println(trimmed); 
} 

uscita:

The quick brown... 
+0

Puoi spiegare la regex? Mi piace la soluzione, anche se dovrò vedere come si rafforza la velocità saggio per la risposta di Ali sotto. – AMZFR

+0

@AMZFR non usare regex se ti preoccupi della velocità. Sarà molto più lento di 'indexOf' +' substring' (10-100 volte più lento). –

+1

Grazie a @Banthar, mi stavo appoggiando semplicemente perché mi piace sapere cosa sta succedendo nel codice, tuttavia la soluzione regex è piuttosto elegante. – AMZFR

4

Prova seguente codice:

private String trim(String src, int size) { 
    if (src.length() <= size) return src; 
    int pos = src.lastIndexOf(" ", size - 3); 
    if (pos < 0) return src.substring(0, size); 
    return src.substring(0, pos) + "..."; 
} 
+0

Questo è bello e semplice. Grazie! –

0

io uso questo hack: supponiamo che la stringa rifilato deve avere 120 di lunghezza:

String textToDisplay = textToTrim.substring(0,(textToTrim.length() > 120) ? 120 : textToTrim.length()); 

     if (textToDisplay.lastIndexOf(' ') != textToDisplay.length() &&textToDisplay.length()!=textToTrim().length()) { 

      textToDisplay = textToDisplay + textToTrim.substring(textToDisplay.length(),textToTrim.indexOf(" ", textToDisplay.length()-1))+ " ..."; 
     }