Ich versuche, die gleichen Austauschanweisungen mehrere tausend Mal auf verschiedene Eingabezeichenfolgen mit so wenig Overhead wie möglich anzuwenden. Ich brauche zwei Dinge dafür zu berücksichtigen:Effiziente und nicht-interferierende Methode zum Ersetzen mehrerer Teilstrings in einem String
- Die Suche Strings sind nicht unbedingt alle gleich lang: man kann nur „a“ sein, ein anderer könnte „ch“ sein, noch eine andere sein könnte „sch“
- Was bereits ersetzt wurde, darf nicht wieder ersetzt werden: Wenn die Ersatzmuster [a-> e; e-> a], "beat" sollte "baet" werden, nicht "baat" oder "beet".
Mit dem im Verstand, das ist der Code, den ich mit aufkommen:
public class Replacements {
private String[] search;
private String[] replace;
Replacements(String[] s, String[] r)
{
if (s.length!=r.length) throw new IllegalArgumentException();
Map<String,String> map = new HashMap<String,String>();
for (int i=0;i<s.length;i++)
{
map.put(s[i], r[i]);
}
List<String> sortedKeys = new ArrayList(map.keySet());
Collections.sort(sortedKeys, new StringLengthComparator());
this.search = sortedKeys.toArray(new String[0]);
Stack<String> r2 = new Stack<>();
sortedKeys.stream().forEach((i) -> {
r2.push(map.get(i));
});
this.replace = r2.toArray(new String[0]);
}
public String replace(String input)
{
return replace(input,0);
}
private String replace(String input,int i)
{
String out = "";
List<String> parts = Arrays.asList(input.split(this.search[i],-1));
for (Iterator it = parts.iterator(); it.hasNext();)
{
String part = it.next().toString();
if (part.length()>0 && i<this.search.length-1) out += replace(part,i+1);
if (it.hasNext()) out += this.replace[i];
}
return out;
}
}
Und dann
String[] words;
//fill variable words
String[] s_input = "ou|u|c|ch|ce|ci".split("\\|",-1);
String[] r_input = "u|a|k|c|se|si".split("\\|",-1);
Replacements reps = new Replacements(s_input,r_input);
for (String word : words) {
System.out.println(reps.replace(word));
}
(s_input
und r_input
bis zu dem Benutzer sein würde, so dass sie‘ nur Beispiele, genau wie das Programm nicht wirklich println()
)
Dies verwenden würde Code stellt sicher, dass längere Suchstrings zuerst gesucht werden und deckt auch die zweite Bedingung ab.
Es ist jedoch ziemlich teuer. Was wäre der effizienteste Weg, um das zu erreichen, was ich hier mache (besonders wenn die Anzahl der Strings in words
sehr groß ist)?
Mit meinem aktuellen Code „Couch“ sollte in „kuc“ umgewandelt werden (außer es nicht, offenbar, es tut jetzt, dank der -1 in split(p,-1)
)
Sie werden Probleme mit 'split (" | ")' (das Argument ist eine Regex) haben. Sie sollten 'split (" \\ | ")' verwenden, wenn Sie wirklich müssen; aber es wäre besser, Ihre Map explizit zu konstruieren und diese als Parameter an 'Replacements' zu übergeben. –
Der 'split (" | ") -Teil soll nur veranschaulichen, was in' s_input' und 'r_input' sein würde. Der tatsächliche Code würde diese Inhalte unterschiedlich ableiten. Aber ich werde den Code hier bearbeiten, um das zu beseitigen. – joelproko
Um ehrlich zu sein, wenn Sie so wenig Overhead wie möglich wollen, wäre Ihre ideale Lösung, das char-Array (einmal) zu wiederholen und den Verlauf für irgendeinen Ersatz zu verfolgen, der mehr als einen char ersetzt. Aka ditching jeden Regex. – Rogue