英文:
Replacing multiple characters in Java with other multiple characters?
问题
我看到有一些类似的问题,但那里的答案对我没有真正帮助。
无论如何,我有一个像这样的字符串:"Today is Saturday"。我需要将每个字符'a'更改为'b',每个字符'o'更改为'f'。基本上是用多个字符替换多个字符。现在,我尝试过像这样做:
String string.replace("a","b").replace("o","f");
但它只执行第一次替换。我尝试过使用StringBuilder:
stringBuilder.append(string);
for (int i=0; i<stringBuilder.length(); i++){
char c=stringBuilder.charAt(i);
if (c=='a'){
我不知道如何在这里替换为'b'...
}
}
stringBuilder.toString();
我读到可以使用映射(maps),但我以前从未使用过,也不知道如何做。有谁可以帮助我解决这个问题吗?
英文:
I've seen that there's some similar questions to this one, but answers there didn't really help me.
Anyways, I have a string like this "Today is Saturday". I need to change every char 'a' to 'b' and every char 'o' to 'f'. Basically, replacing multiple characters with multiple characters. Now, I've tried doing something like this:
String string.replace("a","b").replace("o","f");
But it only does the first replacement. I've tried using Stringbuilder:
stringBuilder.append(string);
for (int i=0; i<stringBuilder.length(); i++){
char c=stringBuilder.charAt(i);
if (c=='a'){
I don't know how to replace it here to 'b'...
}
}
stringBuilder.toString();
I've read I could use maps but I've never used them before and don't know how to do it. Can anyone please help me out with this?
答案1
得分: 0
像您想要的是类似于 SQL 的 `TRANSLATE` 函数的方法。
```lang-java
public static String translate(String input, String fromChars, String toChars) {
if (fromChars.isEmpty() || fromChars.length() != toChars.length())
throw new IllegalArgumentException();
if (input == null || input.isEmpty())
return input;
char[] buf = input.toCharArray();
for (int i = 0; i < buf.length; i++) {
char ch = buf[i];
for (int j = 0; j < fromChars.length(); j++) {
if (fromChars.charAt(j) == ch) {
buf[i] = toChars.charAt(j);
break;
}
}
}
return new String(buf);
}
测试
System.out.println(translate("Today is Saturday", "ao", "bf"));
输出
Tfdby is Sbturdby
这是一个使用 Map
的版本,它支持来自补充平面的 Unicode 字符,例如表情符号:
public static String translate(String input, String fromChars, String toChars) {
// 构建码点映射表
if (fromChars.isEmpty() || fromChars.length() < toChars.length()) {
throw new IllegalArgumentException("fromChars 不能比 toChars 短 (" +
fromChars.length() + " < " + toChars.length() + ")");
}
Map<Integer, String> map = new HashMap<>();
for (int fromIdx = 0, fromEnd, toIdx = 0; fromIdx < fromChars.length(); fromIdx = fromEnd) {
fromEnd = fromChars.offsetByCodePoints(fromIdx, 1);
String mapped = "";
if (toIdx < toChars.length()) {
int toEnd = toChars.offsetByCodePoints(toIdx, 1);
mapped = toChars.substring(toIdx, toEnd);
toIdx = toEnd;
}
if (map.put(fromChars.codePointAt(fromIdx), mapped) != null) {
throw new IllegalArgumentException("fromChars 中索引 " + fromIdx + " 处有重复值: " +
fromChars.substring(fromIdx, fromEnd));
}
}
// 映射码点
if (input == null || input.isEmpty())
return input;
StringBuilder buf = new StringBuilder();
for (int idx = 0, end; idx < input.length(); idx = end) {
end = input.offsetByCodePoints(idx, 1);
String mapped = map.get(input.codePointAt(idx));
buf.append(mapped != null ? mapped : input.substring(idx, end));
}
return buf.toString();
}
测试
System.out.println(translate("Today is Saturday 😀", "ao😀r", "bf😕"));
输出
Tfdby is Sbtudby 😕
请注意,由于 toChars
较短,r
被删除了。这就是 SQL 的 TRANSLATE
函数的工作方式。
<details>
<summary>英文:</summary>
Sounds like you want a method similar to the SQL `TRANSLATE` function.
```lang-java
public static String translate(String input, String fromChars, String toChars) {
if (fromChars.isEmpty() || fromChars.length() != toChars.length())
throw new IllegalArgumentException();
if (input == null || input.isEmpty())
return input;
char[] buf = input.toCharArray();
for (int i = 0; i < buf.length; i++) {
char ch = buf[i];
for (int j = 0; j < fromChars.length(); j++) {
if (fromChars.charAt(j) == ch) {
buf[i] = toChars.charAt(j);
break;
}
}
}
return new String(buf);
}
Test
System.out.println(translate("Today is Saturday", "ao", "bf"));
Output
Tfdby is Sbturdby
Here is a version using Map
, which supports Unicode characters from the Supplemental Planes, e.g. Emojis:
public static String translate(String input, String fromChars, String toChars) {
// Build codepoint mapping table
if (fromChars.isEmpty() || fromChars.length() < toChars.length()) {
throw new IllegalArgumentException("fromChars cannot be shorter than toChars (" +
fromChars.length() + " < " + toChars.length() + ")");
}
Map<Integer, String> map = new HashMap<>();
for (int fromIdx = 0, fromEnd, toIdx = 0; fromIdx < fromChars.length(); fromIdx = fromEnd) {
fromEnd = fromChars.offsetByCodePoints(fromIdx, 1);
String mapped = "";
if (toIdx < toChars.length()) {
int toEnd = toChars.offsetByCodePoints(toIdx, 1);
mapped = toChars.substring(toIdx, toEnd);
toIdx = toEnd;
}
if (map.put(fromChars.codePointAt(fromIdx), mapped) != null) {
throw new IllegalArgumentException("Duplicate value in fromChars at index " + fromIdx + ": " +
fromChars.substring(fromIdx, fromEnd));
}
}
// Map codepoints
if (input == null || input.isEmpty())
return input;
StringBuilder buf = new StringBuilder();
for (int idx = 0, end; idx < input.length(); idx = end) {
end = input.offsetByCodePoints(idx, 1);
String mapped = map.get(input.codePointAt(idx));
buf.append(mapped != null ? mapped : input.substring(idx, end));
}
return buf.toString();
}
Test
System.out.println(translate("Today is Saturday 😀", "ao😀r", "bf😕"));
Output
Tfdby is Sbtudby 😕
Notice how the r
is removed, because toChars
is shorter than fromChars
. This is how the SQL TRANSLATE
function works.
专注分享java语言的经验与见解,让所有开发者获益!
评论