Автоинкрементные буквы в Perl - PullRequest
12 голосов
/ 18 августа 2010

Я не понимаю автоинкрементные буквы в Perl.

Этот пример кажется вполне понятным:

$a = 'bz'; ++$a;
ca #output

b увеличивается до c. Для z не осталось ничего, чтобы перейти к a (или, по крайней мере, так я вижу процесс).

Но потом я сталкиваюсь с такими утверждениями:

$a = 'Zz'; ++$a;
AAa #output

и

$a = '9z'; ++$a;
10 #output

Почему увеличение Zz не возвращает Aa? И почему увеличение 9z не возвращает 0z?

Спасибо!

Ответы [ 6 ]

23 голосов
/ 18 августа 2010

В кавычках perlop :

Если, однако, переменная использовалась только в строковых контекстах с момента ее установки и имеет значение, которое не является пустой строкойи соответствует шаблону /^[a-zA-Z]*[0-9]*\z/, приращение выполняется в виде строки, сохраняя каждый символ в пределах его диапазона, с переносом.

Диапазоны: 0-9, AZ и az.Когда требуется новый персонаж, он берется из диапазона первого символа.Каждый диапазон независим;символы никогда не покидают диапазон, в котором они начали.

9z не соответствует шаблону, поэтому он получает числовое приращение.(Вероятно, должно выдаваться предупреждение «Аргумент не числовой», но в Perl 5.10.1 это не так.) Цифры допускаются только после всех букв (если они есть), никогда перед ними.

Обратите внимание, что строковая цифра соответствует шаблону, а получает приращение строки (если оно никогда не использовалось в числовом контексте).Однако результат приращения строки в такой строке идентичен числовому приращению, за исключением того, что он имеет бесконечную точность и ведущие нули (если таковые имеются) сохраняются.(Таким образом, вы можете заметить разницу только тогда, когда число цифр превышает то, что может хранить IV или NV, или если оно имеет начальные нули.)

Я не понимаю, почему вы думаете, Zz должно стать Aa (если вы не думаете о модульной арифметике, но это не так).Это становится AAa посредством этого процесса:

  1. Увеличение z оборачивается до a.Увеличение предыдущего символа.
  2. Увеличение Z оборачивается до A.Предыдущего символа не существует, поэтому добавьте первый из этого диапазона, который является другим A.

Оператор диапазона (..), если заданы две строки(и левый соответствует шаблону), использует приращение строки для создания списка (это объясняется в конце этого раздела).Список начинается с левого операнда, который затем увеличивается до:

  1. Значение равно правому операнду или
  2. Длина значения превышает длинуправого операнда.

Возвращает список всех значений.(Если случай 2 завершил список, окончательное значение не включается в него.)

6 голосов
/ 18 августа 2010
  1. Поскольку (игнорируя регистр на данный момент; регистр просто сохраняется, с ним ничего интересного не происходит), «AA» является преемником «Z», так как же он может быть преемником «ZZ '?Преемником 'ZZ' является 'AAA'.

  2. Поскольку в отношении ++ и всех других числовых операторов, "9z" - просто глупый способ записи 9,и преемник 9 равен 10. Специально задано специальное поведение автоинкремента строк, которое встречается только в цепочках букв или цепочках букв, за которыми следуют цифры (и никак не смешиваются).

3 голосов
/ 18 августа 2010

Ответ не делать этого.Автоматическое увеличение числа ++ без чисел полно неприятных ловушек.Он подходит только для быстрых взломов.

Вам лучше написать собственный итератор для такого рода вещей:

#!/usr/bin/perl

use strict;
use warnings;

{ package StringIter;

    sub new {
        my $class = shift;
        my %self  = @_;
        $self{set}   = ["a" .. "z"] unless exists $self{set};
        $self{value} = -1           unless exists $self{value};
        $self{size}  = @{$self{set}};

        return bless \%self, $class;
    }

    sub increment {
        my $self = shift;
        $self->{value}++;
    }

    sub current {
        my $self = shift;
        my $n    = $self->{value};
        my $size = $self->{size};
        my $s    = "";

        while ($n >= $size) {
            my $offset  = $n % $size;
            $s          = $self->{set}[$offset] . $s;
            $n         /= $size;
        }
        $s = $self->{set}[$n] . $s;

        return $s;
    }

    sub next {
        my $self = shift;
        $self->increment;
        return $self->current;
    }
}

{
    my $iter = StringIter->new;

    for (1 .. 100) {
        print $iter->next, "\n";
    }
}

{
    my $iter = StringIter->new(set => [0, 1]);

    for (1 .. 7) {
        print $iter->next, "\n";
    }
}
2 голосов
/ 18 августа 2010

Вы спрашиваете, почему инкремент не распространяется.

Если бы это было так, это бы не было приращением. Приращение означает, что у вас есть полностью упорядоченный набор и элемент в нем, и вы создаете следующий более высокий элемент, поэтому он никогда не сможет вернуть вас к более низкому элементу. В этом случае общий порядок - это стандартный алфавитный порядок строк (который определяется только для английского алфавита), расширенный для обработки произвольных строк ASCII таким образом, который кажется естественным для некоторых общих типов строк идентификаторов.

Обтекание также отрицательно сказалось бы на его назначении: обычно вы хотите использовать его для создания произвольного числа различных идентификаторов какого-либо рода.

Я согласен с вердиктом Часа Оуэнса: применять эту операцию к произвольным строкам - плохая идея, это не тот вид использования, для которого она была предназначена.

Я не согласен с его лекарством: просто выберите простое начальное значение, при котором приращение ведет себя разумно, и все будет в порядке.

0 голосов
/ 11 июля 2018

=> В случае буквенно-числовых строк, начинающихся с символа, подобного 'bz' или 'Zz', начинайте двигаться справа. Первый символ - это 'z'. Как вы говорите, нигде нет увеличения 'z' поэтому он увеличивается до «a», но дополнительная цифра переносится на следующую цифру слева. Так что «b» увеличивается до «c». Теперь во втором случае Z не видит никакого алфавита слева от него. В таких случаях создается дополнительная копия текущей цифры, когда она увеличивается.

=> В случае буквенно-цифровых строк, начинающихся с цифры, такой как '9z', perl считает это ошибкой, допущенной пользователем, и считает ее числом, предшествующим строке (в данном случае 9), и увеличивает значение число. Итак, 9 становится 10.

Plz. поправь меня если я не прав

0 голосов
/ 18 августа 2010

Я не понимаю, почему увеличение Zz вернуло бы Aa; как ты думаешь почему? Увеличение на 9z похоже на то, что Perl думает, что 9z - это число 9, а не какая-то странность с базовым уровнем 36.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...