[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[技术讨论] Perl交换两个数组

本帖最后由 523066680 于 2014-10-1 22:10 编辑

交换两个数组的内容

方法一、
列表赋值,限定长度使得元素对号入座
  1. my @a=(1..5);
  2. my @b=('a'..'g');
  3. (@a[0..$#b], @b[0..$#a]) = (@b, @a);
复制代码
方法二、
交换地址。
  1. local (@a, @b);
  2. @a=(1..5);
  3. @b=('a'..'g');
  4. (*a, *b) = (\@b, \@a);
复制代码
或者
  1. (*a, *b) = (*b{ARRAY}, *a{ARRAY});
复制代码
方法二中的数组定义不能是my
参考《Perl语言编程》第二章 集腋成裘 - typeglob (类型团)
所有这些都只影响全局(包)变量;词法不能通过符号表记录访问。



补充: 第一种方法只在两个数组长度相同时适用,之前测试的时候疏忽了。
1

评分人数

    • CrLf: 大赞PB + 40 技术 + 1

回复 3# 523066680


做了个实验,结果把我看迷糊了,为什么长数组在后的时候,交换时就会自动变短:
  1. my @a=(1..5);
  2. my @b=('a'..'g');
  3. (@a[0..$#b], @b[0..$#a]) = (@b, @a);
  4. print "\@a = @a\n\@b = @b\n\n";
  5. my @b=(1..5);
  6. my @a=('a'..'g');
  7. (@a[0..$#b], @b[0..$#a]) = (@b, @a);
  8. print "\@a = @a\n\@b = @b\n\n";
复制代码
更诡异的是,交换得到的短数组和原生数组也不太一样,好像变“聪明”了:
  1. my @a=(1..5);
  2. my @b=('a'..'g');
  3. (@a[0..$#b], @b[0..$#a]) = (@b, @a);
  4. print "\@a = @a\n\@b = @b\n\n";
  5. (@a[0..$#b], @b[0..$#a]) = (@b, @a);
  6. print "\@a = @a\n\@b = @b\n\n";
复制代码
--------------------------------------------------------
卧槽,天书...mark 一个,待消化

TOP

本帖最后由 523066680 于 2014-10-1 22:08 编辑

回复 2# CrLf


      你这么一试,试出问题了,之前测试正确是因为 b 比 a 长,所以
重新赋值后等于扩充覆盖a ,但是如果b比a短, 就变成了不完全覆盖。
还真是只适合长度相等的情况。所以方法一也不可取了。

第二种方法在一楼给了出处

*var 代表以var为名的所有数据类型,包括%var $var @var ... ,
*v2 = *var 就会获得一系列以v2为别名的类型团,这个时候@v2 = @var, $v2 = $var ... 以此类推
他们都是指向同一个数据地址的。如果只要指向某种类型,可以通过\$var ,或者 *var{SCALAR}的方法
指定某个类型。

以下是书籍内容:
《Perl语言编程》第二章 集腋成裘
类型团如今的主要用途是把一个符号表取另一个符号表名字做别名。别名就是外号,如果你说:

*foo = *bar;

那所有叫“foo”的东西都是每个对应的叫“bar”的同意词。你也可以通过给类型团赋予引用实现只给某一个变量取别名:

*foo = \$bar;

这样 $foo 就是 $bar 的一个别名



第十章 -  包
当你执行任意下列的赋值的时候,你实际上只是替换了类型团里的一个引用:
  1.    *sym = \$frodo;
  2.    *sym = \@sam;
  3.    *sym = \%merry;
  4.    *sym = \&pippin;
复制代码
如果你从另外一个角度来考虑问题,类型团本身可以看作一种散列,它里面有不同类型的变量记录。在这种情况下
,键字是固定的,因为一个类型团正好可以包含一个标量,一个散列,等等。但是你可以取出独立的引用,象这样:
  1.    *pkg::sym{SCALAR}      # 和 \$pkg::sym 一样
  2.    *pkg::sym{ARRAY}      # 和 \@pkg::sym 一样
  3.    *pkg::sym{HASH}               # 和 \%pkg::sym 一样
  4.    *pkg::sym{CODE}               # 和 \&pkg::sym 一样
  5.    *pkg::sym{GLOB}                # 和 \*pkg::sym 一样
  6.    *pkg::sym{IO}               # 内部的文件/目录句柄,没有直接的等价物
  7.    *pkg::sym{NAME}               # “sym”(不是引用)
  8.    *pkg::sym{PACKAGE}         # “pkg”(不是引用)
复制代码
你可以通过说 *foo{PACKAGE} 和 *foo{NAME} 找出 *foo 符号表记录来自哪个名字和包。这个功能对那些传递类型
团做参数的子过程里很有用

TOP

方法一测试有点问题:
  1. perl -e "my @a=(1..5);my @b=(6..8);(@a[0..$#b], @b[0..$#a]) = (@b, @a);print \"@a\""
复制代码
输出
6 7 8 4 5

这是不是说明只有不同类型才能直接用方法一?
----------------------------------------------
方法二太棒了,请教下这里的 * 是什么东东?

TOP

返回列表