我正在尝试将相同的替换指令应用于不同的输入字符串数千次,并且开销尽可能小。我需要考虑两件事:
考虑到这一点,这是我提出的代码:
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;
}
}
然后
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
和r_input
取决于用户,因此它们只是示例,就像程序实际上不会使用println()
一样)
此代码可确保首先查找较长的搜索字符串,并涵盖上述第二个条件。
然而,这是非常昂贵的。什么是最有效的方法来完成我在这里做的事情(特别是如果words
中的字符串数量非常大)?
使用我当前的代码,“沙发”应该转换为“kuc”(除非它没有,显然;它现在确实如此,感谢split(p,-1)
中的-1)
答案 0 :(得分:1)
这不是一个完整的解决方案,但它展示了如何扫描输入并在一次通过中查找所有目标子串。您可以使用public static void main(String[] args) throws Exception
{
Pattern p = Pattern.compile("(ou|ch|ce|ci|u|c)");
Matcher m = p.matcher("auouuchcceaecxici");
while (m.find())
{
MatchResult r = m.toMatchResult();
System.out.printf("s=%d e=%d '%s'\n", r.start(), r.end(), r.group());
}
}
来汇总结果,查找当前正在执行的地图中的替换。使用开始和结束索引来处理不匹配段的复制。
s=1 e=2 'u'
s=2 e=4 'ou'
s=4 e=5 'u'
s=5 e=7 'ch'
s=7 e=8 'c'
s=8 e=10 'ce'
s=12 e=13 'c'
s=15 e=17 'ci'
输出:
{{1}}
请注意,正则表达式中的字符串必须按照下降长度的顺序排序才能正常工作。
答案 1 :(得分:0)
可以从密钥生成正则表达式模式并将其留给该模块进行优化。
显然
"(ou|u|ch|ce|ci|c)"
需要通过反向排序或立即作为树来处理ce / ci / c:
"(c(e|h|i)?|ou|u)"
然后
String soughtKeys = "ou|u|ch|ce|ci|c"; // c last
String replacements = "u|a|c|se|si|k";
Map<String, String> map = new HashMap<>();
... fill map
Pattern pattern = Pattern.compile("(" + soughtKeys + ")");
for (String word : words) {
StringBuffer sb = new StringBuffer();
Matcher m = pattern.matcher(word);
while (m.find()) {
m.appendReplacement(sb, map.get(m.group());
}
m.appendTail(sb);
System.out.printf("%s -> %s%n", word, sb.toString());
}
优势在于正则表达式非常智能(虽然速度很慢),并且替换不会替换为替换文本。
答案 2 :(得分:0)
{{1}}