统计字符串中一行中字符的出现次数。

huangapple go评论57阅读模式
英文:

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&lt;Integer&gt; countGroupLengths(String src, char c) {

    Pattern p = Pattern.compile(c + &quot;+&quot;); // e.g. `9+` works too
    Matcher m = p.matcher(src);
    List&lt;Integer&gt; result = new ArrayList&lt;&gt;();
    while (m.find()) {
        String group = m.group(1);
        result.add(group.length());
    }
    return result;
}

test:

System.out.println(countGroupLengths(&quot;ABBB99999SHJ99JI&quot;, &#39;9&#39;));

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&lt;Character, List&lt;Integer&gt;&gt; buildMapOfGroups(String src) {

    return src.chars()     // IntStream
              .mapToObj(c -&gt; (char) c)
              .map(c -&gt; Map.entry(
                      c, // key
                      Pattern.compile(c + &quot;+&quot;).matcher(src)
                             .results()
                             .map(r -&gt; r.group().length())
                             .collect(Collectors.toList())
              ))
              .collect(Collectors.toMap(
                  Map.Entry::getKey, Map.Entry::getValue, 
                  (e1, e2) -&gt; e1, LinkedHashMap::new));
}

For the given source: System.out.println(buildMapOfGroups(&quot;ABBB99999SHJ99JI&quot;));
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

huangapple
  • 本文由 发表于 2020年10月13日 22:50:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/64337573.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定