Java:用对应的 ID 替换给定字符串上的数字
Java: Substitution of numbers on a given String with the correspondent ID
我有这样的字符串:
"[1] ,[2,4], [1,2,3] ,[12,42]..." 具有不可预测的结构(即其中可能有更多括号或更多数字).
这些数字对应于包含在HashMap 中的某个id。
例如:
1->Apollo11
2->纽约12
4->你好3
...
42->乔4
...
我怎样才能将字符串中的数字替换为相应的 id 而不会产生歧义?
例如,如果我用数字替换数字,我可以有:
替换1->连属于12的1都会受影响
如果我从最大的数字开始,即42,当4被代入时,连Joe4中的“4”都会受到影响。
感谢您的关注。
正如您已经发现的那样,简单地用相关名称替换数字的出现有几个缺点:
- 如果您的字符串很大或者您有大量的对,您将需要多次传递,这可能意味着性能显着下降
- 如果您将数字从大到小替换,您仍然可以 运行 遇到问题,例如,如果您只有 4 的映射,因此您仍将 4 替换为 42
- 使用正则表达式,您可以匹配未被字符或其他数字包围的数字,但这可能会进一步提高性能,但仍然有些脆弱,例如如果您将 1 替换为
Apollo 11
然后再替换 11
.
因此,最安全的方法可能是在数字处拆分字符串,遍历标记,替换任何数字并重新加入元素。
示例:
Map<String, String> mapping = ...;
String input = "[1] ,[2,4], [1,2,3] ,[12,42]";
String[] elements = input.split("(?<=\d++|\D++)");
StringBuilder result = new StringBuilder();
for( String element : elements ) {
//simple way to get around checking whether an element is a number:
//if there is nothing mapped, use the element itself - this also keeps unmapped numbers
String replacement = mapping.get( element );
result.appdend( replacement != null ? replacement : element );
}
用于拆分的正则表达式中的一些词:
(?<=...)
是零宽度向后看,即它匹配 ...
表达式任何匹配之前的任何位置。
\d++|\D++
用肯定量词匹配任何数字或非数字序列(即尽可能匹配并且不 "give back" 匹配)。
整个表达式匹配您的数字之前的位置和任何非数字之前的位置(或者换句话说:在您的数字之后)。
这是我的解决方案(未完善,但希望您能理解)。由于缺少查找值,我只是将所有值替换为 **value**
作为示例:
public static void main(String[] args) {
String input = "[1] ,[2,4], [1,2,3] ,[12,42]...";
int start = -1;
StringBuilder builder = new StringBuilder();
for (int idx = 0; idx < input.length(); idx++) {
char c = input.charAt(idx);
if (start == -1) {
if (Character.isDigit(c)) {
start = idx;
} else {
builder.append(c);
}
} else if (!Character.isDigit(c)) {
builder.append(valueOf(input.substring(start, idx)) + c);
start = -1;
}
}
if (start != -1) {
builder.append(valueOf(input.substring(start, input.length())));
}
System.out.println(builder);
}
private static String valueOf(String num) {
int val = Integer.parseInt(num);
return map.getOrDefault(val,"**" + val + "**");
}
输出:
[**1**] ,[**2**,**4**], [**1**,**2**,**3**] ,[**12**,**42**]...
您必须将表达式 map.getOrDefault(val,"**" + val + "**")
替换为对包含替换字符串的地图的引用。
我有这样的字符串:
"[1] ,[2,4], [1,2,3] ,[12,42]..." 具有不可预测的结构(即其中可能有更多括号或更多数字).
这些数字对应于包含在HashMap 中的某个id。 例如:
1->Apollo11
2->纽约12
4->你好3
...
42->乔4
...
我怎样才能将字符串中的数字替换为相应的 id 而不会产生歧义? 例如,如果我用数字替换数字,我可以有:
替换1->连属于12的1都会受影响
如果我从最大的数字开始,即42,当4被代入时,连Joe4中的“4”都会受到影响。
感谢您的关注。
正如您已经发现的那样,简单地用相关名称替换数字的出现有几个缺点:
- 如果您的字符串很大或者您有大量的对,您将需要多次传递,这可能意味着性能显着下降
- 如果您将数字从大到小替换,您仍然可以 运行 遇到问题,例如,如果您只有 4 的映射,因此您仍将 4 替换为 42
- 使用正则表达式,您可以匹配未被字符或其他数字包围的数字,但这可能会进一步提高性能,但仍然有些脆弱,例如如果您将 1 替换为
Apollo 11
然后再替换11
.
因此,最安全的方法可能是在数字处拆分字符串,遍历标记,替换任何数字并重新加入元素。
示例:
Map<String, String> mapping = ...;
String input = "[1] ,[2,4], [1,2,3] ,[12,42]";
String[] elements = input.split("(?<=\d++|\D++)");
StringBuilder result = new StringBuilder();
for( String element : elements ) {
//simple way to get around checking whether an element is a number:
//if there is nothing mapped, use the element itself - this also keeps unmapped numbers
String replacement = mapping.get( element );
result.appdend( replacement != null ? replacement : element );
}
用于拆分的正则表达式中的一些词:
(?<=...)
是零宽度向后看,即它匹配...
表达式任何匹配之前的任何位置。\d++|\D++
用肯定量词匹配任何数字或非数字序列(即尽可能匹配并且不 "give back" 匹配)。
整个表达式匹配您的数字之前的位置和任何非数字之前的位置(或者换句话说:在您的数字之后)。
这是我的解决方案(未完善,但希望您能理解)。由于缺少查找值,我只是将所有值替换为 **value**
作为示例:
public static void main(String[] args) {
String input = "[1] ,[2,4], [1,2,3] ,[12,42]...";
int start = -1;
StringBuilder builder = new StringBuilder();
for (int idx = 0; idx < input.length(); idx++) {
char c = input.charAt(idx);
if (start == -1) {
if (Character.isDigit(c)) {
start = idx;
} else {
builder.append(c);
}
} else if (!Character.isDigit(c)) {
builder.append(valueOf(input.substring(start, idx)) + c);
start = -1;
}
}
if (start != -1) {
builder.append(valueOf(input.substring(start, input.length())));
}
System.out.println(builder);
}
private static String valueOf(String num) {
int val = Integer.parseInt(num);
return map.getOrDefault(val,"**" + val + "**");
}
输出:
[**1**] ,[**2**,**4**], [**1**,**2**,**3**] ,[**12**,**42**]...
您必须将表达式 map.getOrDefault(val,"**" + val + "**")
替换为对包含替换字符串的地图的引用。