Perl排序比较器中修改字符串为何第二种写法能保留原前缀?
为什么第二种Perl排序写法能保留原前缀?
这问题踩中了Perl sort函数里一个很容易忽略的细节——sort比较块里的$a和$b是原数组元素的别名,不是独立副本!
咱们拆解两种写法的差异:
第一种写法:直接修改$a/$b导致原元素被改动
print for sort { $a =~ s/^STRING//; $b =~ s/^STRING//; foo($a) cmp foo($b) } @a;
这里的$a和$b并不是原数组元素的“复制版”,而是直接指向原数组里的元素本身。当你执行s/^STRING//替换时,相当于直接修改了原数组中对应的元素。所以等排序完成后,原数组里的元素已经被去掉了前缀,print输出自然就没前缀了。
第二种写法:用副本避免修改原元素
print for sort { $x = $a; $y = $b; $x =~ s/^STRING//; $y =~ s/^STRING//; foo($x) cmp foo($y) } @a;
这里$x = $a是把$a的值复制给了新变量$x,相当于创建了一个和原元素完全独立的副本。之后对$x和$y做替换操作,只会改动这两个副本,根本碰不到原数组里的元素。所以排序完成后,原数组的元素还是带着原始前缀,print输出自然就能保留前缀了。
简单总结:Perl给sort的比较块传的是原元素的“引用别名”,不是拷贝。直接改$a/$b就是改原数据,用中间变量存值再修改,才不会影响原数组。
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

