perl 数组引用_Perl中数组引用的魔力
perl 数组引用
在编程世界中,如果不遇到嵌套的数据结构,您将走得很远。 例如,JavaScript对象可能如下所示:
var cats = { "name":"Mr. Tickles", "owners": { "owner1" : "Tom", "owner2" : "Janet" }, "color":"orange};
在此示例中,我们在较大的cats对象内嵌套了多个所有者对象。 我们也可以对数组使用类似的东西:
var array1 = [["one", "two"], ["three", "seven", "five"]];
在这里,我们有一个嵌套数组或一个数组数组。
在JavaScript中,您可以使用点表示法或方括号表示法访问嵌套对象。 对于数组,您可以调用array1[0]
并且此调用的预期输出将是该数组中的第一个数组,即[“one”, “two”]
。
这是我们在Perl中访问数据的方式的主要区别。 尽管两种语言的语法都非常相似,但是在Perl中访问嵌套数据可能会有些困难。 例如,如果上面有相同的嵌套数组,并且保存数组数组的变量是@array1
,并且我们想访问$ array1中的第一个数组,并使用调用@array1[0],
实际获得的输出将是第一个元素“one”.
其原因是因为Perl展平了所有嵌套数据。 如果您的数组包含多个数组,则Perl会将其解释为单个数组,并将所有数组数据混搭在一起。 Perl还以非常相似的方式解释对象或哈希。
输入数组引用
如果您不打算在访问数据时将所有数据弄平,那么最好的解决方案是在定义数组变量时使用数组引用。 这是在创建数组时完成的,远远早于我们打算访问该数组的时间。 如果数据没有存储为参考,我们将无法访问它作为参考。
在上面的示例中,我们可以按如下方式定义它:
my @array1 = ();
在这里,我们只是创建一个空数组来保存嵌套数组。 接下来,我们可以将新数组推入数组容器。
my @nestedArray = ("one", "two");my @nestedArray2 = ("five", "seven", "three");
在这一点上,我们可能会尝试使用以下内容:
push @array1, @nestedArray;
这将完全实现我们以前的扁平数组。 相反,在将数组推入容器数组之前,我们将创建该数组的引用。
创建参考:
my $nestedArray = \@nestedArray;
这将创建一个包含嵌套数组引用的标量变量。 该引用实际上是使用反斜杠符号创建的。
现在,我们可以复制上面的代码,将引用推入数组:
push @array1, $nestedArray;
解引用引用的数组:
使用相同的格式,我们可以将尽可能多的嵌套数组推入数组容器。 稍后,我们可能要访问这些引用。 首先,让我们想象一下嵌套数据如下所示:
@array1 = [[1, 2, 4], [3, 4, 5], [8, 8, 9], [6, 7, 6]];
在这里,我们在一个数组容器内嵌套了四个数组,每个嵌套的数组包含3个整数。 让我们尝试访问最后一个嵌套数组中的第一个整数。
首先,访问引用数组的语法有些棘手。 首先,我将代码放在此处,然后解释其工作方式:
@{ $array1[3] }[0];
大括号前面的@符号告诉Perl我们正在访问数组,而array变量前面的$(标量)符号使我们只能访问容器中的单个数组。 [3]让我们访问数组的第四个元素,该元素位于索引[3]处。 这使我们获得了系列中的最后一个数组,然后在该块的结尾,我们有了熟悉的[0],它告诉Perl我们想要该数组中的第一个元素。 我们的预期回报为6。
现在,让我们看一个更复杂的问题,在这个问题中,我们必须在循环内使用许多引用。 这是称为最大路径总和的问题。 取以下数字三角形:
3,
7、4
2 4 6
8、5、9、3
这里的对象是从顶部到底部,并找到最大的求和路径,仅向右移动或向左移动。 例如,在第二行中,如果我们选择7,则无法访问6。在此示例中,最大总和路径为3、7、4、9,总和为23。
了解了解决方案后,让我们使用Perl和数组引用来解决该问题。 首先要记住的是,对于较大的三角形,将无法使用蛮力(尝试数字的每种组合)来解决此问题。 解决此类问题的最佳方法实际上是向后工作。 我们将从第3行开始,例如,并针对当前数字下两个可能数字的总和测试每个数字。 第一个数字为2,我们可能的组合为8和5。这里最大的和为10(8 + 2)。 在对每个数字进行此过程之后,我们只需删除最后一行,而仅用最高的总和替换第三行。 我们的新三角形如下所示:
3,
7、4
10、13、15
现在,我们将在第二行中执行相同的操作,这将给我们:
3,
20、19
然后是最后一行,这将给我们23。
从编程的角度考虑这个过程,而不是三角形,我们的数据输入可能是单个数组:
my @triangle = (3,7,4,2,4,6,8,5,9,3);
从这里开始,我们的过程可能是将其分成几行。 这就是嵌套引用数组起作用的地方。 我们最终想要得到的是这样的:
my @triangle = ([3],[7,4],[2,4,6],[8,5,9,3]);
最简单的方法是遍历数组,为每个嵌套数组创建引用,然后将其推入新数组。
这是我们可以做到的一种方法:
my @choppedTriangle = []; my @chopped = (); #Our new array containermy $start = 0;my $stop = 0;my $length = 1;my $row = 1;my $triangle = @triangle ;while ( @choppedTriangle < @triangle ) {my @row = ();for (my $i=$start; $i <= $stop; $i++) {push @choppedTriangle , $triangle[$i];push @row , $triangle[$i];};
my $row = \ @row ;push @chopped , $row;$start = $stop + 1;$length = $length + 1;$stop = $stop + $length;};
在这里,我们在while循环中使用for循环。 在循环中,在每次迭代时,我们都将每个@row推入@choppedTriangle中。 这不是数组引用,而是有目的的。 在这种情况下,我们应该只具有4个嵌套数组,并且我们不希望推送超过4个嵌套数组。 @triangle也有4个嵌套数组,因此我们的while循环条件语句将在两个数组彼此相等时立即停止。 将所有行都推入@choppedtriangle后,我们想结束循环。
这项工作将全部在我们的for循环中完成。 在for循环之外,但仍在while循环中,我们将为每行创建一个数组引用,您可以在行中看到以下内容:
my $row = \@row;push @chopped , $row;
然后,将该引用推入@chopped数组中。 我只将@choppedtriangle用作while循环的条件,一旦循环完成,就不再需要使用它了。 但是,我需要的所有嵌套数组都包含在@chopped中。
我还在循环中使用$ start,$ stop和$ length变量,使用这些变量作为索引来确定每一行的开始和结束。 例如,两者都从0开始,这将是[$ start]的索引。 由于我们要提取的第一个元素在索引0处,因此这是完美的。 在每个循环之后,我们将调整变量$ start和$ stop,以使Perl知道新行的长度。 新行将从第一行结束处开始,因此:
$start = $stop + 1;
然后,长度也将是$length = $length + 1
,因为我们从第1行开始,并且随后的每一行都长一个字符。 然后,无论新长度是多少,我们都将使用该值来设置新的$stop
变量,该变量将在长度之后仅一个字符,从而使我们能够获得介于新的$start
和$stop
变量之间的所有内容。
有了这一点,我们现在应该有了一个包含4个嵌套数组的数组。 我们接下来要做的是遍历数组,然后遍历每个嵌套数组。 我们将要做前面提到的相同的事情,将当前行与其下一行进行比较,并用最大的和替换这些值。 我的想法是这样。 假设我们当前的行是这样的:
[2,4],而其下一行是[1,2,3]。
我将创建一个临时数组,并在第一行进行迭代。 由于数组的长度仅为2,因此此循环将仅包含2次迭代。在每次迭代中,我将进行2个比较:2 + 1和2 + 2,然后是4 + 2和4 + 3。 在每次迭代中,我将采用最大的比较和,并将其推入临时数组。 因此,我的临时数组现在将保存值[4,7]。
接下来,我将[2,4]的上一行替换为新的临时数组[4,7]。
最后,我将重置正在处理的行,新行将成为三角形的下一行,并且将重置我正在比较的行,这将是我们刚设置的行,[4, 7]。
让我在这里放入将要使用的代码,然后说明如何实现它:
首先,我将创建两个变量来控制要迭代的行:
my $iter = 1;
my $iter2 = 2;
我的想法是,在每个循环的末尾更改这些变量,这将允许我移至下一行。
my @tempArray = ();my $chopRows = @chopped -1;for (my $i=0; $i < $chopRows; $i++) { @tempArray = ();for (my $i=0; $i < @{ $chopped[scalar @chopped -$iter2] }; $i++) {
if(@{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i] > @{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i+1]){push @tempArray , @{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i];}else{push @tempArray ,@{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i+1];};};@{ $chopped[scalar @chopped -$iter2] } = @tempArray ;$iter = $iter + 1;$iter2 = $iter2 + 1;};
第一部分可能看起来很奇怪:
my @tempArray = ();my $chopRows = @chopped -1;for (my $i=0; $i < $chopRows; $i++) { @tempArray = ();
由于我正在创建临时数组,然后在for循环内再次调用它。 原因是,当for循环结束时,我应该在其中包含表示总和的新值。 一旦回到循环的开始,就需要清空临时数组。 由于我是在循环外创建数组的,因此,如果我没有在每个循环的开始处将其内容清空,那么在第4次迭代(三角形的第4行)中,我们将获得一个数组,其中包含所有和的总和三角形…当我们想要的只是当前行时。 现在,在第二个循环中,我们有:
for (my $i=0; $i < @{ $chopped[scalar @chopped -$iter2] }; $i++) {
现在,这只是一个非常基本的for循环,中间有一个花哨的长度控制。 @{ $chopped[scalar @chopped -$iter2] };
希望这看起来很熟悉,因为这正是我们之前用来取消引用数组并访问其内容的方式:
@{ $array1[3] }[0];
[scalar @chopped -$iter2]
此处, $iter2
变量当前为2,它指向倒数第二行,基本上从@chopped
数组的末尾开始工作,并向后@chopped
两个位置。 这意味着,我们将遍历倒数第二行中的数字,并将其与最后一行进行比较。 完成后,我们可以将$iter2
更改$iter2
3,或者简单地将$iter2 = $iter2 + 1
。 这将允许我们从末尾访问第三行,然后我们可以继续重复此过程。
为简单起见,在for循环中只有一个条件语句。 这会将当前整数与其下的两个可能整数进行比较。
if(@{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i] > @{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i+1])
在这里,我们正在访问解引用数组@{ $chopped[scalar @chopped -$iter2] }[$i]
。 这表示上一行的当前迭代,我们正在查看它与@{ $chopped[scalar @chopped -$iter] }[$i]
的总和是否大于@{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i+1])
。 在这里,我们同时使用了变量$ iter2和$ iter,为我们提供了每一行的值,$ iter是最后一行,$ iter2是上面一行。
如果此条件返回true,则推入当前值:
@tempArray , @{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i];
否则,我们推其他价值。 这样,我们不需要比较值是否相等。 因为如果第一个值不大,则无论如何我们都会推入另一个值,因为它们是否相同并不重要。
最后,在循环结束时,我们重置当前行的值,将其替换为temparray的值,还重置$ iter和$ iter2变量的值:
@{ $chopped[scalar @chopped -$iter2] } = @tempArray ;$iter = $iter + 1;$iter2 = $iter2 + 1;
这使我们回到循环的顶部,在此我们重置@temparray值,并从下一行开始。 现在,我们可以打印@tempArray的值,该值将保留最终值。
foreach my $x ( @tempArray ) { print "$x \n";}
要一起查看整个代码块,这是我所拥有的:
#!/usr/bin/perluse strict;use warnings;# By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.# 3,# 7, 4# 2, 4, 6# 8, 5, 9, 3# 23!# starting triangle arraymy @triangle = (3,7,4,2,4,6,8,5,9,3);# array to holdmy @choppedTriangle = [];my @chopped = ();my $start = 0;my $stop = 0;my $length = 1;my $row = 1;my $triangle = @triangle ;while ( @choppedTriangle < @triangle ) {my @row = ();for (my $i=$start; $i <= $stop; $i++) {push @choppedTriangle , $triangle[$i];push @row , $triangle[$i];};
my $row = \ @row ;push @chopped , $row;$start = $stop + 1;$length = $length + 1;$stop = $stop + $length;};my $iter = 1;my $iter2 = 2;
my @tempArray = ();my $chopRows = @chopped -1;for (my $i=0; $i < $chopRows; $i++) { @tempArray = ();for (my $i=0; $i < @{ $chopped[scalar @chopped -$iter2] }; $i++) {
if(@{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i] > @{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i+1]){push @tempArray , @{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i];}else{push @tempArray ,@{ $chopped[scalar @chopped -$iter2] }[$i] + @{ $chopped[scalar @chopped -$iter] }[$i+1];};};@{ $chopped[scalar @chopped -$iter2] } = @tempArray ;$iter = $iter + 1;$iter2 = $iter2 + 1;};
foreach my $x ( @tempArray ) { print "$x \n";}
这可能有点麻烦,但是我发现当习惯于在Perl中引用和取消引用嵌套数据时,诸如此类的复杂情况可以帮助我理解正在发生的事情以及它如何如此有用。 让我知道您是否有任何反馈!
翻译自: https://hackernoon.com/the-magic-of-array-references-in-perl-cb0bdd82a448
perl 数组引用
perl 数组引用_Perl中数组引用的魔力相关推荐
- java 指针 引用_java中的引用与c中的指针
指针 首先要弄清楚指针和c中的指针是不一样的,前者是概念,后者是具体实例. 换句话说,C中的指针只是指针中的一种,其他语言也有指针,比如C++.但是我们同别人交流的时候,大都不会从概念上去交流,一般会 ...
- c语言变量定义数组,C语言中数组的定义和使用
一.1.一维数组的定义: 类型说明符 数组名[常量表达式]; 注意:常量表达式包括常量与符号常量,不能包含变量. 2.一维数组的引用: 数组名[下标]; 3.一维数组的初始化: a.在定义数组时 ...
- php中不让数组初始化,javascript中数组与php数组初始化差异
准确来说,javascript中我们需要称之为数组对象,因为数组就是对象,不信你看: var a=[1,2,3]; //竟然会弹出object alert(typeof(a)); 之前学习php的时候 ...
- 数组方法 + ES6中数组方法 + 数组的空位
目录 1.静态方法 1.Array.isArray() Array.isArray方法返回一个布尔值,表示参数是否为数组.它可以弥补typeof运算符的不足. 2.Array.from() 用于将两类 ...
- python定义数组变量_python中数组用法
增加时a.append( 'a ')就可以了.只要按顺序加,就没有问题 . 使用时,完全可以使用下标: 代码如下 复制代码 a[0] a[1] 但出果引用不存在的下标,则会引发异常.这时,你需要先添加 ...
- java 数组 内存_Java 中数组的内存分配
Java 中数组的内存分配 1.Java 程序在运行时,需要在内存中分配空间.为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据和内存管理方式. 2.数组基本概念 数组是 ...
- python中的引用_Python中的引用
我有一个多播网络,需要不断地向所有其他用户发送数据.我不想让程序员不断地改变数据包的发送方式.正因为如此,我试图找出如何引用Python中的任何对象或变量(我是Python新手),这样用户就可以修改它 ...
- java 软引用_Java中弱引用和软引用的区别以及虚引用和强引用介绍
知道弱引用和软引用的概念与如何使用它们是两码事,引用类在垃圾回收工作的过程中有重要作用.我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型 ...
- java 数组参数_java中 数组可以作为形式参数传递到调用的方法中吗?要怎么操作?...
展开全部 可以,操作代码如下: public class ArrTest{ public static void doTest(String[] args){ for(int i=0;i System ...
最新文章
- 嵌入式开发之davinci--- 8148/8168/8127 中的图像缩放sclr、swms之后出现图像视频卡顿、屏幕跳跃的问题...
- linux c 判断字符串是否是数字
- java ancestor_java – 家谱祖先查找算法
- 命令行模式下的后向引用替换
- GitLab安装配置使用总结
- Java中的位运算符、移位运算
- Python基础之内置函数(二)
- python timedelta_Python使用笔记:时间的运算timedelta
- OpenWRT上如何让 ss 设置指定域名dst bypass
- 三相滤波器怎么接线_三相电源滤波器作用 详解三相电源滤波器
- 宝塔面板ftp空间连接失败解决方案汇总
- 程序员的浪漫之——情侣日常小程序
- ubuntu16.04安装GNU Radio
- 微信公众号开发踩坑指南(3)——公众号返回超链接点击跳转并自动关闭
- 客户端专项测试-启动时间测试
- 数模赛常用外挂工具汇总(骚操作)
- 画皮SAP-世界管理软件公司的中国真相
- text/html和text/plain的区别
- 个人运营APP要投入多少钱?开发是小头,推广是大头!
- 对我们来说,如何避免成为一个油腻的产品经理?
热门文章
- 人性23——论如何凑字数,作家示范版
- android surfaceflinger内存,surfaceflinger中的显示内存管理类
- 研发转FAE,要想清楚
- html textarea 插件,在TextArea中呈现HTML
- 从零基础到考取HCIP,我是如何去系统学习网工知识的
- 华硕编程竞赛11月JAVA专场 C题太空遨游 题解
- 2022 CCF中国软件大会(CCF ChinaSoft)“金融科技前沿技术与发展”论坛成功召开...
- php cacti,cacti搭建遇到的那些事
- 第三方账号登录的原理
- 中国月销售额10万元以下小规模纳税人不再交增值税