用于从数组中删除重复值的Perl习惯用法:
@uniq = keys %{{map{$_=>1}@list}}
使用这个版本更便宜:
@uniq = keys %{{map{$_=>undef}@list}}
我用这些单行测试了它,似乎在某些版本的Perl上都是如此:
perl -e 'my %x; $x{$_} = 1 for 0..1000_000; system "ps -ovsz $$"' perl -e 'my %x; $x{$_} = undef for 0..1000_000; system "ps -ovsz $$"'
解决方法
好吧,undef应该是一个flyweight值,这意味着对它的所有引用都指向相同的数据.你没有得到其他文字.您仍然需要引用它的插槽的开销.但是,我没有看到它为我在Mac OS X上的Perl 5.10或5.11保存任何内存.虽然perl可能没有在unf情况下使用更多内存,但我敢打赌它预计会使用更多内存,所以它无论如何都要抓住它.但是,我现在并不热衷于调查内部的内存使用情况.
Devel::Peek对于展示这些东西非常方便:
#!perl use Devel::Peek; my $a = undef; my $b = undef; Dump( $a ); Dump( $b ); my %hash = map { $_,undef } 1 .. 3; $hash{4} = 'Hello'; Dump( \%hash );
输出看起来有点吓人,但你看到undef值是NULL(0x0)而不是单个字符串值(PV):
SV = NULL(0x0) at 0x100208708 REFCNT = 1 FLAGS = (PADMY) SV = NULL(0x0) at 0x100208738 REFCNT = 1 FLAGS = (PADMY) SV = RV(0x100805018) at 0x100805008 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x100208780 SV = PVHV(0x100809ed8) at 0x100208780 REFCNT = 2 FLAGS = (PADMY,SHAREKEYS) ARRAY = 0x100202200 (0:5,1:2,2:1) hash quality = 91.7% KEYS = 4 FILL = 3 MAX = 7 RITER = -1 EITER = 0x0 Elt "4" HASH = 0xb803eff9 SV = PV(0x100801c78) at 0x100804ed0 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x100202a30 "Hello"\0 CUR = 5 LEN = 8 Elt "1" HASH = 0x806b80c9 SV = NULL(0x0) at 0x100820db0 REFCNT = 1 FLAGS = () Elt "3" HASH = 0xa400c7f3 SV = NULL(0x0) at 0x100820df8 REFCNT = 1 FLAGS = ()