【发布时间】:2014-10-11 16:18:07
【问题描述】:
我想交换一个字符串中的两个字母。例如,如果输入是W 和H,则字符串中所有出现的W 都应替换为H,所有出现的H 应替换为W。字符串WelloHorld 将变为HelloWorld。
我知道如何替换单个字符:
str = str.replace('W', 'H');
但我不知道如何交换字符。
【问题讨论】:
我想交换一个字符串中的两个字母。例如,如果输入是W 和H,则字符串中所有出现的W 都应替换为H,所有出现的H 应替换为W。字符串WelloHorld 将变为HelloWorld。
我知道如何替换单个字符:
str = str.replace('W', 'H');
但我不知道如何交换字符。
【问题讨论】:
public String getSwappedString(String s)
{
char ac[] = s.toCharArray();
for(int i = 0; i < s.length(); i++)
{
if(ac[i] == 'H')
ac[i]='W';
else if(ac[i] == 'W')
ac[i] = 'H';
}
s = new String(ac);
return s;
}
【讨论】:
Java8 真的很简单
static String swap(String str, String one, String two){
return Arrays.stream(str.split(one, -1))
.map(s -> s.replaceAll(two, one))
.collect(Collectors.joining(two));
}
使用示例:
public static void main (String[] args){
System.out.println(swap("???", "?", "?"));
}
我敦促您不要将 Character 用于交换功能,因为它会破坏包含 BMP 之外的字母的字符串
如果你想扩展它以使用任意字符串(不仅仅是字母),你可以引用提供的字符串:
static String swap(String str, String one, String two){
String patternOne = Pattern.quote(one);
String patternTwo = Pattern.quote(two);
return Arrays.stream(str.split(patternOne, -1))
.map(s -> s.replaceAll(patternTwo, one))
.collect(Collectors.joining(two));
}
【讨论】:
hello[world] 中交换[ 和] 时抛出PatternSyntaxException
Character.isLetter('[')是false,而Character.isLetter(Character.toCodePoint("?".charAt(0), "?".charAt(1))) 是 true...无论如何这可以很容易地解决
您可能需要三个替换调用才能完成此操作。
第一个将其中一个字符更改为中间值,第二个进行第一次替换,第三个将中间值替换为第二次替换。
String str = "Hello World";
str = star.replace("H", "*").replace("W", "H").replace("*", "W");
编辑
针对以下有关在String 中交换字符的这种方法的正确性的一些担忧。即使String 中已经存在*,这也将起作用。但是,这需要在返回新的String 之前首先转义任何出现的* 并取消转义这些额外步骤。
public static String replaceCharsStar(String org, char swapA, char swapB) {
return org
.replace("*", "\\*")
.replace(swapA, '*')
.replace(swapB, swapA)
.replaceAll("(?<!\\\\)\\*", "" + swapB)
.replace("\\*", "*");
}
编辑 2
阅读其他一些答案后,一个新版本不仅适用于 Java 8,还可以替换需要在正则表达式中转义的字符,例如[ 和 ] 并考虑到使用 char 原语来操作 String 对象的担忧。
public static String swap(String org, String swapA, String swapB) {
String swapAEscaped = swapA.replaceAll("([\\[\\]\\\\+*?(){}^$])", "\\\\$1");
StringBuilder builder = new StringBuilder(org.length());
String[] split = org.split(swapAEscaped);
for (int i = 0; i < split.length; i++) {
builder.append(split[i].replace(swapB, swapA));
if (i != (split.length - 1)) {
builder.append(swapB);
}
}
return builder.toString();
}
【讨论】:
String 的替代方法。更喜欢哪一个将取决于使用它的情况。在这个简单的Hello World 案例中,这并不重要。但话又说回来,循环 char 数组对于单个字符可能编码为多个 chars 的语言并不理想。
replace 函数的替代方法提到捷豹。
字符串扫描方法的稍微好一点的版本,没有显式的数组和索引访问:
StringBuilder sb = new StringBuilder();
for (char c : source_string.toCharArray()) {
if (c == 'H') sb.append("W");
else if (c == 'W') sb.append("H");
else sb.append(c);
}
return sb.toString();
【讨论】:
您可以遍历字符串的字符数组,并在看到任一字符时交换:
private static String swap(String str, char one, char two) {
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == one) {
chars[i] = two;
} else if (chars[i] == two) {
chars[i] = one;
}
}
return String.valueOf(chars);
}
【讨论】:
你也可以试试这个代码。
System.out.println("WelloHorld".replaceAll("W", "H~").replaceAll("H(?!~)", "W").replaceAll("(?<=H)~", ""));
输出:
HelloWorld
使用输入字符串中不存在的任何字符代替~。
【讨论】: