Как увеличивать значения в списке? - PullRequest
2 голосов
/ 11 июля 2020

Я неоднократно пытался найти этот вопрос, но не могу сформировать поиск, который дает результаты, которые действительно имеют отношение к моему вопросу.
Я пытаюсь создать сценарий, который анализирует файл SVG (XML текстовый формат файл, который создает содержимое графа c) ищет определенные c подсказки и присваивает значения RGB. (Каждое значение RGB будет немного отличаться.)
Для этого я представляю несколько увеличивающихся переменных (например, $ i, $ j и $ k), которые увеличиваются в зависимости от триггеров, обнаруженных при анализе текстового файла. Однако суммы, которые мне нужно увеличить, не равны «1». Кроме того, необходимые значения являются шестнадцатеричными. Я мог бы настроить что-то, где переменные увеличиваются на заданную величину, например +33, но мне также нужно будет преобразовать числа в шестнадцатеричный, выяснить, как начать заново, и т. Д. c.

A Мне приходит в голову гораздо более универсальный, мощный и элегантный подход, но я не знаю, как go об этом.
Как мне настроить эти увеличивающие переменные для увеличения значений, которые я установил в массиве ?
Например, мои потенциальные значения RGB равны @rgbval = (00,33,66,99, cc, ff).
Как я могу сделать $ i go из одного значения в этом списке до следующего?
Еще лучше, как я могу сделать так, чтобы $ i ++ (или что-то подобное) означало " go к значению следующего элемента в @ rgbval"?
И если это возможно, как я могу сказать Perl начать с элемента [0] после достижения конца массива?

Ответы [ 2 ]

3 голосов
/ 11 июля 2020

Итак, у вас есть строка, которая представляет собой шестнадцатеричное представление числа

my $hex = 'cc';

Чтобы выполнить арифметические операции c, вам сначала нужно преобразовать это в число.

my $num = hex($hex);

Теперь мы можем произвести арифметику c на нем.

$num += 33;

Если мы хотим преобразовать его обратно в шестнадцатеричный, мы можем использовать

$hex = sprintf("%02x", $num);

$i обычно используется для индексов . Если это то, что вы хотите, вы можете использовать следующее:

for my $i (0..$#rgbval) {
   # Do something with $i and/or $rgbval[$i]...
}

Если вместо этого вы хотите, чтобы $i принимал каждое значение, вы можете использовать следующее:

for my $i (@rgbval) {
   # Do something with $i...
}

Но, похоже, вам нужен счетчик, который оборачивается вокруг.

Простым решением будет использование оператора if.

my $i = 0;
while (...) {
   # Do something with $i and/or $rgbval[$i]...

   ++$i;
   $i = 0 if $i == @rgbval;
}

Но я бы использовал по модулю арифметики c.

my $i = 0;
while (...) {
   # Do something with $i and/or $rgbval[$i]...

   $i = ( $i + 1 ) % @rgbval;
}

В качестве альтернативы вы можете повернуть массив.

while (...) {
   # Do something with $rgbval[0]...

    push @rgbval, shift(@rgbval);
}
1 голос
/ 11 июля 2020

Икегами, какая отличная информация содержится в вашем ответе.
Я нашел три ваших предложения слишком привлекательными, чтобы их игнорировать, и попытался понять их. Ваш первый раздел был посвящен обработке описанной математики, преобразованию в шестнадцатеричное и обратно.
Я попытался превратить эти шаги в сценарий «проверки концепции» вместе с вашим предложением о сбросе по модулю. (Хорошо, «тест на понимание концепции».)
Для тестового сценария я использовал итератор вместо поиска инициирующего события, что казалось более простым.
Цель состояла в том, чтобы увеличить значения через шестнадцатеричные числа, перечисленные в примере массива, и начать заново после последнего значения. Итак, я повторил до десяти раз, чтобы дать значениям возможность начать заново.
После того, как я понял, что мне нужно каждый раз добавлять 51 вместо 33, чтобы получить эти примерные значения, а также нужно было увеличить числовое значение моего массива в 51 раз, поскольку я увеличивал на 51, это сработало довольно хорошо:

my $num = hex("00");
my @rgbval = qw(a b c d e f);
for my $i (0..10) {
   print ( "For i=$i, \$num is " , sprintf("%02x ", $num) , "\n");
   $num = ( $num + 51 ) % ( 51 * @rgbval );
}

вывод:
~ \ Perlscripts> iterate2.pl
Для i = 0, $ num равно 00
Для i = 1, $ num равно 33
Для i = 2, $ num равно 66
Для i = 3, $ num равно 99
Для i = 4, $ num равно cc
Для i = 5, $ num равно ff
Для i = 6, $ num равно 00
Для i = 7, $ num равно 33
Для i = 8, $ num равно 66
Для i = 9, $ num равно 99
Для i = 10, $ num равно cc

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

my @hue = qw(00 33 66 99 cc ff);
my $v = 0;
for my $i (0..10) {
   print "\$i=$i, \$hue[$v]=" , $hue[$v] , "\n";
   $v = ( $v + 1 ) % @hue;
}

output:
~ \ Perlscripts> iterate2.pl
$ i = 0, $ hue [0] = 00
$ i = 1, $ hue [1] = 33
$ i = 2, $ hue [2 ] = 66
$ i = 3, $ hue [3] = 99
$ i = 4, $ hue [4] = cc
$ i = 5, $ hue [5] = ff
$ i = 6, $ hue [0] = 00
$ i = 7, $ hue [1] = 33
$ i = 8, $ hue [2] = 66
$ i = 9, $ hue [3] = 99
$ i = 10, $ hue [4] = cc

Ваше последнее предложенное решение, вращение массива с помощью pu sh и сдвиг показались, пожалуй, самым новым подходом и весьма убедительным, особенно когда я понял, что если у меня есть переменная, которая хранит смещенное значение, это будет правильное значение для pu sh в следующий раз, где угодно. При таком подходе мне даже не нужно беспокоиться о том, чтобы начать заново после последнего значения; изменяющийся массив позаботится об этом автоматически для меня:

my @hue = qw(00 33 66 99 cc ff); 
for my $i (0..10) {
   my $curval = shift(@hue);
   print "\$i=$i, \$curval is $curval               \.\.\.And the array is currently: ( @hue )\n";
   push(@hue,$curval);
}

output:
~ \ Perlscripts> iterate2.pl
$ i = 0, $ curval равно 00 ... И в настоящее время массив имеет вид: (33 66 99 cc ff)
$ i = 1, $ curval - 33 ... И в настоящее время массив имеет вид: (66 99 cc ff 00)
$ i = 2, $ curval равно 66 ... И в настоящее время массив имеет следующий вид: (99 cc ff 00 33)
$ i = 3, $ curval равно 99 ... И в настоящее время массив: (cc ff 00 33 66)
$ i = 4, $ curval - это cc ... И массив в настоящее время: (ff 00 33 66 99)
$ i = 5, $ curval - это ff ... И в настоящее время массив имеет вид: (00 33 66 99 cc)
$ i = 6, $ curval равно 00 ... И в настоящее время массив: (33 66 99 cc ff)
$ i = 7, $ curval равно 33 ... И массив в настоящее время: (66 99 cc ff 00)
$ i = 8, $ curval равен 66 ... И в настоящее время массив: (99 cc ff 00 33)
$ i = 9, $ curval равно 99 ... И в настоящее время массив имеет следующий вид: (cc ff 00 33 66)
$ i = 10, $ curval - cc. ..И сейчас массив: (ff 00 33 6 6 99)

Самый познавательный и полезный! Большое спасибо.

...