2013-11-02 7 views
10

Sto cercando uno molto semplice modo di ottenere l'equivalente di qualcosa come il seguente codice JavaScript. Cioè, per ogni partita vorrei chiamare una certa funzione di trasformazione e usare il risultato come valore di sostituzione.Qual è l'equivalente di Regex-replace-with-function-evaluation in Java 7?

var res = "Hello World!".replace(/\S+/, function (word) { 
    // Since this function represents a transformation, 
    // replacing literal strings (as with replaceAll) are not a viable solution. 
    return "" + word.length; 
}) 
// res => "5 6" 

Solo .. in Java. E, preferibilmente come "metodo singolo" o "modello" che può essere riutilizzato.

risposta

10

La risposta è nella documentazione Matcher#appendReplacement. Basta mettere la tua chiamata di funzione nel ciclo while.

[Il metodo appendReplacement] è concepito per essere utilizzato in un ciclo con i metodi appendTail e find. Il seguente codice, ad esempio, scrive un cane due cani nel cortile al flusso standard di output:

Pattern p = Pattern.compile("cat"); 
Matcher m = p.matcher("one cat two cats in the yard"); 
StringBuffer sb = new StringBuffer(); 
while (m.find()) { 
    m.appendReplacement(sb, "dog"); 
} 
m.appendTail(sb); 
System.out.println(sb.toString()); 
+2

[qui] (http://stackoverflow.com/a/1282099/20938) è una soluzione più completa. Affronta il problema dei segni del dollaro e dei backslash trattati come speciali da 'appendReplacement()'. –

0

Non sono sicuro che le vostre esigenze precise sono, ma qualcosa di simile potrebbe funzionare:

String res = ""; 
for (String piece : "hello world".split(" ")) 
    res += Integer.toString(piece.length()) + " "; 

Ovviamente ci sono altri modi per scriverlo e modifiche che possono essere apportate in base ai requisiti (ad esempio, utilizzare un delimitatore più accurato di uno spazio).

Per un'implementazione precisa dello snippet, è possibile utilizzare ad es. StreamTokenizer con un StringReader e alcuni wrapper per analizzare i delimitatori e inserirli tra i conteggi.

+1

Mentre ciò funzionerebbe qui, sto cercando una soluzione che possa rimanere generica (attraverso l'utilizzo del supporto di espressioni regolari). – user2864740

+0

Ah, sì, questo non sarebbe un buon modo per farlo allora. –

6

Quando permettendo Java 8 è possibile utilizzare lambda-espressioni, per avere un JavaScript piace sostituire:

String result = StringReplacer.replace("Hello World!", Pattern.compile("\\S+"), (Matcher m) -> { 
    return "" + m.group().length(); 
}); 

StringReplacer.java:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class StringReplacer { 
    public static String replace(String input, Pattern regex, StringReplacerCallback callback) { 
     StringBuffer resultString = new StringBuffer(); 
     Matcher regexMatcher = regex.matcher(input); 
     while (regexMatcher.find()) { 
      regexMatcher.appendReplacement(resultString, callback.replace(regexMatcher)); 
     } 
     regexMatcher.appendTail(resultString); 

     return resultString.toString(); 
    } 
} 

StringReplacerCallback.java:

import java.util.regex.Matcher; 

public interface StringReplacerCallback { 
    public String replace(Matcher match); 
} 

Fonte: http://www.whitebyte.info/programming/string-replace-with-callback-in-java-like-in-javascript

+3

Si potrebbe voler chiamare 'Matcher.quoteReplacement' sulla stringa di sostituzione, per evitare che le barre e i simboli del dollaro vengano trattati in modo speciale. – Gareth

+0

@Gareth sarebbe fantastico se si potesse sborsare il [gist] (https://gist.github.com/nickrussler/42f8619f1a36eea25364), migliorarlo e commentare con il link. Quindi aggiornerò il post e il mio gaster appena possibile. –