我想取一个字符串并隔离其中的所有整数,然后将它们存储在一个数组中。
输入字符串将只包含字母a-z(大写和小写),数字0-9和"-"(读作负号).
到目前为止,我已经写了:
String str = readString();
String[] arr = str.split("[^0-9-]+");
如果我的输入字符串是例如"15abc-59abc31abc100"上面的代码工作得很好,我只需要将字符串数组中的每个元素转换为int,但是如果我的输入字符串在数字之间没有字母来分隔它们,它将无法正常工作。abc59-12abc56-10abc10将产生一个只有3个元素的数组:59- 12,56 - 10,10我如何使它识别减号作为数组中新元素的开始而不丢失符号本身?
理想情况下,我希望输入"abc59-12abc56-10abc10"分割后的样子:
String[] arr = {"59","-12","56","-10","10");
readString ();方法将始终提供我上面描述的字符串类型。
您真正想要的是-
是一个有效的'数字符号',但是只能在任何给定数字块的开头。
然而,通过尝试匹配它们之间的负空间,您已经使自己变得困难:这是棘手的,以正则表达式的形式。
但是,如果你走了一条积极的路线(写一个描述一个数字的regexp),那就微不足道了:Pattern.compile("-?\d+")
完美地描述了它:一个可选的减号后面跟着1个或多个数字。很简单。如果你的输入是"aa----5",它有一个匹配序列(-5),它甚至会"工作"。
. .那就这么做吧。你在滥用split
。不要滥用系统,一旦你把事情弄得更复杂一点,它就会变得更糟。
private static final Pattern NUMBER = Pattern.compile("-?\d+");
public List<Integer> getNumbers(String in) {
Matcher m = NUMBER.matcher(in);
var out = new ArrayList<Integer>();
while (m.find()) out.add(Integer.parseInt(m.group(0)));
return out;
}
这里使用了一些技巧:
m.find()
在输入字符串中查找与提供的regexp匹配的下一个子序列。- regexp默认为"贪婪"。意思是,字符串"1234"可以在法律上以多种方式平等地解释:这是一个单独的项目吗(1234)?毕竟,是不是只有"1"也匹配"-?d+"Greedy"意味着regexp将匹配它们所能匹配的最长序列。这正是你想要的,毫无疑问。
m.group(0)
为您提供匹配。0是包含整个查找序列的特殊组。如果你在正则表达式中使用括号,你可以做组,你也可以得到那些,例如,如果你想排除负号,你可以做"-?(\d+)"
-注意括号。现在你可以做m.group(1)
。- 注意,如果必须使用
int[]
,那么将整数列表转换为int[]
需要一个循环。toArray
不能这样做(Integer
不是int
,但List<int>
,目前,仍然是非法的java)。
这是一个一行代码:剥离前导和尾部非数字,然后在非数字/减号上分割,转换为int
,然后收集到一个数组:
int[] numbers = Arrays.stream(str.replaceAll("^\D+|\D+$", "").split("(?=-\d)|[^-\d]+"))
.mapToInt(Integer::parseInt).toArray();
这里的关键是分割,当以下字符是减号然后是数字,或时,它会对既不是减号也不是数字的字符进行零宽度分割。