问题
I tried parsing a common string depiction of ranges (e.g. 1-9
) into actual ranges (e.g. 1 .. 9
), but often got weird results when including two digit numbers. For example, 1-10
results in the single value 1
instead of a list of ten values and 11-20
gave me four values (11 10 21 20
), half of which aren't even in the expected numerical range:
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;
}
This prints:
1 2 3 4 5 6 7 8 9
1
11 10 21 20
Instead of the expected:
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
(I figured this out before posting this question, so I have answered below. Feel free to add your own answer if you'd like to elaborate).
回答1:
The problem is indeed that .split
returns Str
rather than Int
, which the original answer solves. However, I would rather implement my "get_range_for" like this:
sub get_range_for($string) {
Range.new( |$string.split("-")>>.Int )
}
This would return a Range
object rather than an Array
. But for iteration (which is what you most likely would use this for), this wouldn't make any difference. Also, for larger ranges the other implementation of "get_range_for" could potentially eat a lot of memory because it vivifies the Range
into an Array
. This doesn't matter much for "3-10", but it would for "1-10000000".
Note that this implementation uses >>.Int
to call the Int method on all values returned from the .split
, and then slips them as separate parameters with |
to Range.new
. This will then also bomb should the .split
return 1 value (if it couldn't split) or more than 2 values (if multiple hyphens occurred in the string).
回答2:
The result of split
is a Str
, so you are accidentally creating a range of strings instead of a range of integers. Try converting $start
and $stop
to Int
before creating the range:
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;
}
Giving you what you expect:
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
来源:https://stackoverflow.com/questions/44835476/why-are-some-of-my-ranges-insane