为什么我的一些范围疯了?

时间:2017-06-29 21:44:13

标签: perl6

我尝试将范围(例如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;
}

打印:

1 2 3 4 5 6 7 8 9
1
11 10 21 20

而不是预期的:

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

(我在发布这个问题之前想到了这一点,所以我在下面回答。如果你想详细说明,请随意添加你自己的答案。)

2 个答案:

答案 0 :(得分:9)

问题确实是.split返回Str而不是Int,原始答案解决了这个问题。但是,我宁愿像这样实现我的“get_range_for”:

sub get_range_for($string) {
    Range.new( |$string.split("-")>>.Int )
}

这将返回Range个对象而不是Array。但是对于迭代(这是你最有可能使用它),这不会有任何区别。此外,对于较大范围,“get_range_for”的其他实现可能会占用大量内存,因为它将Range转化为Array。这对于“3-10”来说并不重要,但它会用于“1-10000000”。

请注意,此实现使用>>.Int对从.split返回的所有值调用Int方法,然后将它们作为单独的参数单击|Range.new。如果.split返回1值(如果它不能拆分)或超过2个值(如果字符串中出现多个连字符),那么这也会爆炸。

答案 1 :(得分:7)

split的结果是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;
}

给你你期望的东西:

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