我尝试将范围(例如1-9)的常见字符串描述解析为实际范围(例如1 .. 9),但是当包括两位数字时经常得到奇怪的结果.例如,1-10得到单个值1而不是十个值的列表,并11-20给出了四个值(11 10 21 20),其中一半甚至不在预期的数值范围内:
put get_range_for('1-9');
put get_range_for('1-10');
put get_range_for('11-20');
sub get_range_for ( $string ) {
my ($start, $stop) = $string.split('-');
my @values = ($start .. $stop).flat;
return @values;
}
Run Code Online (Sandbox Code Playgroud)
这打印:
1 2 3 4 5 6 7 8 9
1
11 10 21 20
Run Code Online (Sandbox Code Playgroud)
而不是预期的:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
Run Code Online (Sandbox Code Playgroud)
(在发布这个问题之前我已经弄明白了,所以我在下面回答.如果你想详细说明,请随意添加你自己的答案).
问题确实是.split回归Str而不是Int原始答案所解决的问题.但是,我宁愿像这样实现我的"get_range_for":
sub get_range_for($string) {
Range.new( |$string.split("-")>>.Int )
}
Run Code Online (Sandbox Code Playgroud)
这将返回一个Range对象而不是一个Array.但是对于迭代(这是你最有可能使用它),这不会有任何区别.此外,对于更大的范围,"get_range_for"的其他实现可能会占用大量内存,因为它可以将其Range转化为Array.这对于"3-10"来说并不重要,但它会用于"1-10000000".
请注意,此实现用于>>.Int对从其返回的所有值调用Int方法.split,然后将它们作为单独的参数滑动|到Range.new..split如果返回1值(如果它不能拆分)或超过2个值(如果字符串中出现多个连字符),那么这也会爆炸.
结果split是a Str,因此您不小心创建了一系列字符串而不是一系列整数.尝试转换$start并$stop以Int创建范围之前:
put get_range_for('1-9');
put get_range_for('1-10');
put get_range_for('11-20');
sub get_range_for ( $string ) {
my ($start, $stop) = $string.split('-');
my @values = ($start.Int .. $stop.Int).flat; # Simply added .Int here
return @values;
}
Run Code Online (Sandbox Code Playgroud)
给你你期望的东西:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
Run Code Online (Sandbox Code Playgroud)