英文:
Count occurences in a row of a char in string
问题
有没有办法在Java中连续计算字符串中字符的出现次数?
例如,给定字符串:ABBB99999SHJ99JI
,将输出字符串中9
字符连续出现的情况:连续5次出现一次,连续2次出现两次。
我尝试找到解决方案,但没有结果。
可以使用正则表达式找到,但对于每个数字数量,我需要创建一个单独的正则表达式。
英文:
Is there any way to count occurences of a char in string in a row in Java?
For example, given string: ABBB99999SHJ99JI
, will output that 9
char was find in a string once: 5 times in a row and twice: 2 times in a row.
I tried to find the solution, but without result.
It is possible to find it with regex, but for each amount of numbers i need to create a separate one.
答案1
得分: 1
可以按照你提到的正则表达式的方法来实现:
- 创建一个正则表达式来查找至少包含一个字符的分组,例如
([9]+)
- 在循环中查找这些分组并收集它们的长度。
public static List<Integer> countGroupLengths(String src, char c) {
Pattern p = Pattern.compile(c + "+"); // 例如 `9+` 也可以
Matcher m = p.matcher(src);
List<Integer> result = new ArrayList<>();
while (m.find()) {
String group = m.group(1);
result.add(group.length());
}
return result;
}
测试:
System.out.println(countGroupLengths("ABBB99999SHJ99JI", '9'));
输出:
[5, 2]
更新
根据评论中 @Andreas 提供的所有更改,可能值得为每个字符构建一个映射到长度列表的映射:
public static Map<Character, List<Integer>> buildMapOfGroups(String src) {
return src.chars() // IntStream
.mapToObj(c -> (char) c)
.map(c -> Map.entry(
c, // 键
Pattern.compile(c + "+").matcher(src)
.results()
.map(r -> r.group().length())
.collect(Collectors.toList())
))
.collect(Collectors.toMap(
Map.Entry::getKey, Map.Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
}
对于给定的源字符串:System.out.println(buildMapOfGroups("ABBB99999SHJ99JI"));
输出为:
{A=[1], B=[3], 9=[5, 2], S=[1], H=[1], J=[1, 1], I=[1]}
注意:使用 LinkedHashMap 来保持插入顺序
英文:
It can be done using regexp as you mentioned:
- create a regexp to find groups containing at least one character, e.g.
([9]+)
- find the groups in a loop and collect their lengths.
public static List<Integer> countGroupLengths(String src, char c) {
Pattern p = Pattern.compile(c + "+"); // e.g. `9+` works too
Matcher m = p.matcher(src);
List<Integer> result = new ArrayList<>();
while (m.find()) {
String group = m.group(1);
result.add(group.length());
}
return result;
}
test:
System.out.println(countGroupLengths("ABBB99999SHJ99JI", '9'));
output:
[5, 2]
Update<br/>
It may be worth to build a map for each character to the list of lengths
integrating all the changes offered by @Andreas in the comments:
public static Map<Character, List<Integer>> buildMapOfGroups(String src) {
return src.chars() // IntStream
.mapToObj(c -> (char) c)
.map(c -> Map.entry(
c, // key
Pattern.compile(c + "+").matcher(src)
.results()
.map(r -> r.group().length())
.collect(Collectors.toList())
))
.collect(Collectors.toMap(
Map.Entry::getKey, Map.Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
}
For the given source: System.out.println(buildMapOfGroups("ABBB99999SHJ99JI"));
prints:
{A=[1], B=[3], 9=[5, 2], S=[1], H=[1], J=[1, 1], I=[1]}
Note: using LinkedHashMap to keep the order of insertion
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论