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).

+3


source to share


2 answers


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).

+9


source


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

      

+7


source







All Articles