gpt4 book ai didi

regex - 在排序比较器中修改字符串

转载 作者:行者123 更新时间:2023-12-02 06:28:02 25 4
gpt4 key购买 nike

我有以下代码,在排序比较器中,它在进行比较之前删除前缀字符串。

print for sort { 
$a =~ s/^STRING//;
$b =~ s/^STRING//;
foo($a) cmp foo($b)
} @a;

虽然比较和顺序是正确的,但前缀字符串正在从输出中删除。
以下保留前缀字符串(如我所愿)。

print for sort { 
$x = a;
$y = b;
$x =~ s/^STRING//;
$y =~ s/^STRING//;
foo($x) cmp foo($y)
} @a;

但我很困惑第二部分如何保留前缀。
它是否正在复制字符串,如果是数组,是否会剥离原始引用?
另外,我是否在第一个代码片段中做错了什么并最终遇到了这个问题?

最佳答案

一种方法:使用 /r modifier

print for sort {
foo( $a =~ s/^STRING//r ) cmp foo( $b =~ s/^STRING//r )
} @ary

替换运算符 s/ 返回修改后的字符串并保持原始字符串不变。如果没有匹配项,则返回似乎符合目的的原始字符串。如果这用于大型数组,或者函数调用需要时间,请参阅优化的结尾。

另一种方法是将替换更改为匹配捕获,当可行。


sort 中对此进行了广泛的讨论。 .首先,$a$b 是(包)全局变量

The $a and $b are set as package globals in the package the sort() is called from

block { } 代表一个匿名子例程和

... the elements to be compared are passed into the subroutine as the package global variables $a and $b

所以别名意味着改变它们会影响元素。因此

The values to be compared are always passed by reference and should not be modified.

$a$b 发生变化从而元素发生变化时会发生什么。

在第二种情况下,您将 $a$b 复制到(应该是什么!)词法 $x$ y 并且与 @ary 的连接已断开,因此元素未更改。

始终在程序的开头设置use warnings;use strict;。这是一个极好的示例,即使是极端的示例——您引入的用于尝试的变量是全局变量($x)还是词法变量(my $x).


处理元素以使用结果值进行排序比较的代码存在效率缺陷。一次对两个元素进行比较,因此元素会被处理多次。每次我们进行相同的处理并为元素计算相同的值。

这种低效率仅在足够大的数据集上才会显着,而且大多数情况下无需担心。但在这种情况下,一个正则表达式引擎运行并且还涉及一个函数调用,而这些在 Perl 中并不便宜。此外,调用的开销是未指定的,我想这涉及到一些工作。

优化这个可以对输入进行预处理然后排序

my @sorted_ary =  
map { $_->[1] }
sort { $a->[0] cmp $b->[0] }
map { [ foo( s/^STRING//r ), $_ ] }
@ary;

采用输入 @arymap 应用正则表达式和函数调用,并将结果与​​原始元素一起存储在一个双元素 arrayref 中,对于 @ary 的每个元素。然后对这个 arrayrefs 列表进行排序,使用第一个 arrayref 元素进行比较。最后一个 map 从已排序的数组引用中提取第二个元素,从而返回按需要排序的原始项目。

这叫做 Schwartzian transform .请参阅 sort 中的“示例” , 例如。

应该记住,只有在数据足够大的情况下, yield 才会显着,而这种操作也会带来开销(而且代码要复杂得多)。因此,仅当排序存在明显的此类问题时才考虑使用它。

关于regex - 在排序比较器中修改字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50149354/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com