【问题标题】:How to increment through the values in a list?如何递增列表中的值?
【发布时间】:2020-07-10 21:28:27
【问题描述】:

我曾多次尝试搜索此问题,但无法形成与我的问题实际相关的搜索结果。
我正在尝试构建一个脚本来解析 SVG 文件(生成图形内容的 XML 文本格式文件),寻找特定的线索并分配 RGB 值。 (每个 RGB 值会略有不同。)
为此,我描绘了多个递增变量(例如 $i、$j 和 $k),这些变量基于解析文本文件时发现的触发器而递增。 但是,我需要增加的数量不是“1”。此外,所需的值是十六进制形式。 我可以设置变量以给定数量递增的方式,例如 +33,但我还需要将数字转换为十六进制,弄清楚如何重新开始,等等。

我想到了一种更通用、更强大、更优雅的方法,但我不知道如何去做。
如何设置这些递增变量以通过我在数组中设置的值递增?
例如,假设我的 RGB 潜在值为 @rgbval = (00,33,66,99,cc,ff)。
如何使 $i 从这个列表中的一个值变为下一个值?
更好的是,我怎样才能使 $i++(或类似的东西)意味着“转到@rgbval 中的下一个元素的值”?
假设这是可能的,我将如何告诉 Perl 在到达数组末尾后从元素 [0] 重新开始?

【问题讨论】:

  • 您是指"00","33","66","99","cc","ff"(字符串)还是0x00,0x33,0x66,0x99,0xcc,0xff(数字)?
  • 从技术上讲,我正在分配数字,但文本文件本身并不区分数字和字符串,它只是文本。所以我希望增加的值只是字符串格式:"00","33","66","99","cc","ff"

标签: arrays perl iterator increment


【解决方案1】:

所以你有一个数字的十六进制表示的字符串

my $hex = 'cc';

要对其进行算术运算,首先需要将其转换为数字。

my $num = hex($hex);

现在我们可以对其进行算术运算了。

$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;
}

但我会使用模数运算。

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);
}

【讨论】:

  • 关于:for my $i (@rgbval) { # Do something with $i... } 这是我想到的第一个方法,但这里的问题是我没有循环我的潜在值列表,我正在遍历文本文件以根据我当前的增量值查找要更改的位置。
  • if 语句看起来更接近我所希望的,因为它似乎使用了++$i。但是,我不明白这条线的作用:$i = 0 if $i == @rgbval;
  • $i = ( $i + 1 ) % @rgbval; - 这看起来很有趣,我从未见过 % 在数组上使用过,我需要看看它是如何工作的。谢谢!
  • $i = 0 if $i == @rgbval; 与if ($i == @rgbval) { $i = 0; } 相同
  • % 返回除法的余数。标量上下文中的数组返回它包含的元素数。
【解决方案2】:

Ikegami,您的回复包含了多么棒的信息。
我发现你的三个建议太吸引人了,不容忽视,并试图理解它们。您的第一部分是关于处理所描述的数学,转换为十六进制。
我试图将这些步骤结合到“概念测试”脚本中,以及您对模重置的建议。 (好吧,一个“概念理解测试”。)
对于测试脚本,我使用了迭代器而不是搜索触发事件,这似乎更简单。
目标是使值通过示例数组中列出的十六进制数字递增,并在最后一个值。 所以我重复了十次,给价值观一个重新开始的机会。
在我发现每次都需要添加 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;
}

输出:
~\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

您最后提出的解决方案,使用 push 和 shift 旋转数组似乎可能是最新颖的方法并且非常引人注目,尤其是当我意识到如果我有一个存储移位值的变量,那将是下一个 push 的正确值时间,一圈又一圈。 在这种方法中,我什至不必担心在最后一个值之后重新开始;不断变化的数组会自动为我解决这个问题:

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);
}

输出:
~\Perlscripts>iterate2.pl
$i=0, $curval is 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 is 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 66 99 )

最具教育意义和帮助!非常感谢。

【讨论】:

  • my $num = hex("00");是my $num = 0x00;的复杂方式,也就是my $num = 0;
  • 第一个 sn-p 没有任何意义。你永远不会使用@rgbval 的任何值。因此,您最后两个 sn-ps 中的任何一个(删除了 $i++)都是我的选择。
  • @Ikegami 所以,for my $i (0..10) 负责增加 $i? -很高兴知道。 (我是新手。)在第一个 sn-p 中,数组的内容是无关紧要的,因为我每次都是通过数学构造值。您可能已经注意到第一种方法中的数组具有不相关的元素 a 到 f。我唯一真正需要的是数组的大小,我可以完全省略它,只在模数语句中使用“6”,但我知道我稍后会使用数组,所以我试了一下那样。 (但我也最喜欢最后两个 sn-ps。:-)
  • 和那些讨厌的无偿$i++s 已被删除。 :)
  • Re "我本可以完全忽略它,只在我的模语句中使用 "6"",或者使用标量变量而不是数组(例如 my $n = 6; ) /// Re "但我知道我以后会使用数组," 啊,好的。
猜你喜欢
  • 1970-01-01
  • 2018-04-22
  • 2021-09-22
  • 2022-01-18
  • 1970-01-01
  • 2023-01-27
  • 2020-09-28
  • 2012-05-28
  • 1970-01-01
相关资源
最近更新 更多