这个问题是正则表达式实践和单元测试实践的结合。
正则表达式部分
我为了个人练习而编写了这个问题separateThousands
:
Given a number as a string, introduce commas to separate thousands. The number may contain an optional minus sign, and an optional decimal part. There will not be any superfluous leading zeroes.
这是我的解决方案:
String separateThousands(String s) {
return s.replaceAll(
String.format("(?:%s)|(?:%s)",
"(?<=\\G\\d{3})(?=\\d)",
"(?<=^-?\\d{1,3})(?=(?:\\d{3})+(?!\\d))"
),
","
);
}
它的工作方式是对两种类型的逗号进行分类:第一个和其余。在上面的正则表达式中,rest 子模式实际上出现在 first 之前。匹配项的长度始终为零,即 replaceAll
为 ","
。
其余基本上向后查看是否有匹配的后跟 3 位数字的内容,并向前查看是否有数字。这是上一场比赛引发的某种链式 react 机制。
第一个基本上是在后面查找^
anchor ,后跟一个可选的减号,以及 1 到 3 个数字。从该点开始的字符串的其余部分必须匹配三元组数字,后跟一个非数字(可以是 $
或 \.
)。
我对这部分的问题是:
- 这个正则表达式可以简化吗?
- 可以进一步优化吗?
- 在first之前排序rest是有意的,因为first只需要一次
- 没有捕获组
单元测试部分
正如我所提到的,我是这个问题的 author,所以我也是负责为他们提出测试用例的人。它们在这里:
INPUT, OUTPUT
"1000", "1,000"
"-12345", "-12,345"
"-1234567890.1234567890", "-1,234,567,890.1234567890"
"123.456", "123.456"
".666666", ".666666"
"0", "0"
"123456789", "123,456,789"
"1234.5678", "1,234.5678"
"-55555.55555", "-55,555.55555"
"0.123456789", "0.123456789"
"123456.789", "123,456.789"
我在工业强度单元测试方面没有太多经验,所以我想知道其他人是否可以评论这是否是一个很好的覆盖范围,我是否错过了任何重要的内容等等(如果我总是可以添加更多测试)我错过了一个场景)。
最佳答案
这对我有用:
return s.replaceAll("(\\G-?\\d{1,3})(?=(?:\\d{3})++(?!\\d))", "$1,");
第一次通过时,\G
的行为与 ^
相同,并且先行强制 \d{1,3}
消耗仅将匹配位置保留在三位数边界所需的字符数。之后,\d{1,3}
每次都会消耗最多三位数字,并使用 \G
将其固定到上一场比赛的末尾。
对于您的单元测试,我只是在问题描述中明确指出,输入始终是有效数字,最多保留一位小数。
关于java - 使用正则表达式codingBat splitThousands(以及单元测试方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2703689/