数字字符串格式化| 豆包MarsCode AI刷题

71 阅读6分钟

问题描述

小M在工作时遇到了一个问题,他需要将用户输入的不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。小M还发现,有时候输入的数字字符串前面会有无用的 0,这些也需要精简掉。请你帮助小M编写程序,完成这个任务。


测试样例

样例1:

输入:s = "1294512.12412"
输出:'1,294,512.12412'

样例2:

输入:s = "0000123456789.99"
输出:'123,456,789.99'

样例3:

输入:s = "987654321"
输出:'987,654,321'

>正则表达式

  1. 正则表达式基础概念

    • 正则表达式是一种用于匹配和处理文本模式的工具。它使用特定的字符和语法规则来定义这些模式。在 Java 中,java.util.regex包提供了对正则表达式的支持。
    • 例如,在处理文本时,可以用正则表达式来查找符合特定格式的单词、数字或者其他字符序列。
  2. 本问题中使用的正则表达式^0+(?!$)解析

    • ^(脱字符)

      • 这是一个定位符,表示匹配字符串的开始位置。在^0+(?!$)中,它确保了后面的模式匹配是从字符串的开头进行的。例如,对于字符串00123^就定位到了最左边的第一个0的位置,从这里开始检查是否符合后续的0+模式。
    • 0+

      • +是一个量词,表示前面的字符(这里是0)出现一次或多次。所以0+表示匹配一个或多个连续的0。例如,在字符串000中,0+可以匹配整个000部分。
    • (?!$)(零宽负预测先行断言)

      • ?!是负预测先行的语法结构。$表示匹配字符串的结尾位置。整个(?!$)的意思是断言当前位置之后(即紧跟的位置)不是字符串的结尾。结合前面的0+来看,^0+(?!$)就是要匹配字符串开头的连续的0,但前提是这些0的后面还有其他字符,不能是整个字符串只有这些0然后就结束了。例如,对于字符串0,因为后面就是字符串结尾了,就不符合(?!$)这个条件,所以0不会被匹配;而对于字符串001,开头的两个0后面还有1,不是结尾,那就可以匹配这两个0
  3. 正则表达式在代码中的作用

    •  s = s.replaceFirst("^0+(?!$)", "");这行代码中,replaceFirst方法是String类的一个方法,用于将字符串中第一次出现的与给定正则表达式匹配的内容替换为指定的字符串。在这里,就是把通过正则表达式^0+(?!$)匹配到的开头连续的0(符合上述规则的那些0)替换成一个空字符串"",从而达到精简字符串开头无用0的目的。

如何在 Java 中使用正则表达式?

正则表达式在 Java 中的常见应用场景有哪些?

除了 Java,还有哪些编程语言支持正则表达式?

解题思路

1. 去除开头无用的 0

  • 首先,使用正则表达式来处理输入的数字字符串,通过 replaceFirst("^0+(?!$)", "") 语句去除字符串开头连续出现的、且后面还有其他非 0 字符跟随的 0(即保证整个字符串不是单独一个 0 的情况下,把开头多余的 0 删掉)。这一步是为了精简数字字符串的表示,避免不必要的前导 0 干扰后续处理,例如把 "000123" 精简为 "123"

2. 判断是否存在小数部分

  • 通过 indexOf('.') 方法查找字符串中是否存在小数点,根据其返回值来确定接下来的处理方式:

    • 如果返回值为 -1(即不存在小数点) :说明输入的是一个整数,此时需要对这个整数部分添加千分位逗号。
    • 如果返回值不为 -1(即存在小数点) :意味着输入的数字包含整数部分和小数部分,那就需要分别对整数部分添加千分位逗号,然后再原样保留小数部分,最后将处理好的整数部分和小数部分组合起来。

3. 处理整数部分(添加千分位逗号)

  • 无论是整数还是包含小数的数字中的整数部分,添加千分位逗号的思路基本一致:

    • 可以通过循环遍历整数部分的每一位字符。比如对于整数部分字符串 "123456789" ,从左到右依次处理每个字符。
    • 在循环过程中,通过一定的条件判断来决定何时添加逗号。具体判断条件通常是当当前字符索引大于 0(也就是不是第一个字符),并且当前剩余未处理的字符数量是 3 的倍数时,就在当前位置添加一个逗号。例如对于数字 123456789 ,从右往左看,每三位添加一个逗号,就会在 3 、6 这些位置对应的字符前添加逗号,最终变为 "123,456,789"

4. 处理小数部分(原样保留)

  • 如果数字字符串存在小数部分,通过 substring 方法提取出小数点后面的那部分字符串(也就是小数部分),在处理完整数部分后,直接将提取出来的小数部分添加到结果字符串后面即可,不需要对其做额外的格式改变操作,确保小数部分的准确性得以保留。

5. 组合结果并返回

  • 如果是整数,经过添加千分位逗号的处理后,直接将得到的结果字符串返回。
  • 如果是包含小数的数字,在分别处理好整数部分和添加完小数部分后,将它们组合起来形成完整的带千分位逗号且保留小数的数字字符串,再返回这个最终的结果字符串。

解题代码

public class Main {
    public static String solution(String s) {
        // 去除开头连续的无用0,但保留至少一个0的情况(比如0本身这种输入)
        s = s.replaceFirst("^0+(?!$)", "");
        int dotIndex = s.indexOf('.');
        StringBuilder result = new StringBuilder();
        if (dotIndex == -1) {
            // 如果没有小数点,说明是整数部分
            int len = s.length();
            for (int i = 0; i < len; i++) {
                if (i > 0 && (len - i) % 3 == 0) {
                    result.append(',');
                }
                result.append(s.charAt(i));
            }
        } else {
            // 有小数点,分别处理整数部分和小数部分
            String integerPart = s.substring(0, dotIndex);
            String decimalPart = s.substring(dotIndex);
            int intLen = integerPart.length();
            for (int i = 0; i < intLen; i++) {
                if (i > 0 && (intLen - i) % 3 == 0) {
                    result.append(',');
                }
                result.append(integerPart.charAt(i));
            }
            result.append(decimalPart);
        }
        return result.toString();
    }

    public static void main(String[] args) {
        System.out.println(solution("1294512.12412").equals("1,294,512.12412"));
        System.out.println(solution("0000123456789.99").equals("123,456,789.99"));
        System.out.println(solution("987654321").equals("987,654,321"));
    }
}

总结

启发思路

  • 比如对于这道题一开始可能不清楚如何构建整体代码逻辑,AI 能清晰指出先通过正则表达式 “^0+(?!$)” 用replaceFirst方法去除开头无用 0,像对于输入 “00123”,可精简成 “123”。再根据有无小数点分情况添加千分位逗号,给我们搭建好清晰的解题框架,快速引导编程方向。

理解知识

  • 在正则表达式方面,像 “^0+(?!较难理解,可详细解释定位开头、匹配连续、)” 确保后面还有字符等,并用不同输入示例,如 “0” 不符合匹配而 “001” 符合,帮助我们透彻掌握其用法,便于以后处理类似文本操作。
  • 对于字符串处理方法,像解释indexOf用于判断有无小数点,substring提取整数、小数部分等,以具体操作 “123.45” 为例,能清楚展示如何运用这些方法实现功能,加深对字符串操作的理解。

纠错优化

  • 编写代码时若出现语法错误,比如写replaceFirst时参数格式不对,或者逻辑错误导致千分位逗号添加位置不对等情况,把代码给 AI,它就能准确指出问题所在,并给出如简化循环添加逗号逻辑等优化建议,让代码更优质高效。