Why are some of my ranges insane?
I tried to parse the generic range description string (for example 1-9
) into actual ranges (for example 1 .. 9
), but often got weird results when I included two-digit numbers. For example, 1-10
results in a single value 1
instead of a list of ten values, but 11-20
gave me four values ββ( 11 10 21 20
), half of which are not even in the expected numeric 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;
}
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 it out before posting this question, so I answered below. Feel free to add your own answer if you want to clarify).
source to share
The problem is what .split
returns Str
, not Int
which solves the original answer. However, I would rather implement my "get_range_for" like this:
sub get_range_for($string) {
Range.new( |$string.split("-")>>.Int )
}
This will return an object Range
, not Array
. But for iteration (which is what you will most likely use to do this), it doesn't really matter. Also, for large ranges, another implementation of "get_range_for" can potentially consume a lot of memory as it animates Range
in Array
. It doesn't really matter for "3-10", but for "1-10000000".
Note that this implementation uses >>.Int
to call the Int method on all values ββreturned from .split
and then scans them as separate parameters from |
to Range.new
. It will also bomb if the .split
return value is 1 (if it cannot be split) or more than 2 values ββ(if there were multiple hyphens in the line).
source to share
The result split
is Str
, so you arbitrarily create a series of rows instead of a whole row. 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;
}
Providing you with 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
source to share