Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 对Perl数组进行就地排序_Arrays_Perl_Sorting - Fatal编程技术网

Arrays 对Perl数组进行就地排序

Arrays 对Perl数组进行就地排序,arrays,perl,sorting,Arrays,Perl,Sorting,我有一个数组的引用(称为$interval),我想对该数组中的值进行排序。数组中可能有大量的值,所以我不希望复制这些值。我目前的做法是这样的 sub by_position { $a->start <=> $b->start || $a->end <=> $b->end } my @sorted_intervals = sort by_position (@$intervals); sub by_位置 { $a->开始$b->开始||

我有一个数组的引用(称为
$interval
),我想对该数组中的值进行排序。数组中可能有大量的值,所以我不希望复制这些值。我目前的做法是这样的

sub by_position
{
  $a->start <=> $b->start ||
  $a->end   <=> $b->end
}
my @sorted_intervals = sort by_position (@$intervals);
sub by_位置
{
$a->开始$b->开始||
$a->end$b->end
}
my@sorted_interval=按_位置排序(@$interval);

但是,如果我正确理解Perl,这将确实复制数组中的所有值。是这样吗?如果是这样,有没有一种方法可以对数组进行就地排序(使用对该数组的引用)?

自Perl 5.8.4以来,就地排序
@a=sort@a
得到了优化。有关详细信息,请参阅以下链接:

所以你应该能够写:

@$intervals = sort by_position @$intervals

在Perl 5.8.3之后的版本中,您将看到内存使用率的降低(并在极少数情况下保留别名)。

第二个示例将创建一个新的引用:

$x = [ qw( a c b ) ]; say $x; @$x = sort @$x; say $x; $x = [sort @$x]; say $x

.Perl允许使用习惯用法
@arr=sort@arr
对数组进行就地排序。与赋值运算符的正常行为相反,在这种情况下将不制作副本。然而,这种优化仅限于普通数组变量;它不适用于数组引用:

$ perl -MO=Concise -e'my $ref; @$ref = sort @$ref'
e  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
3     <0> padsv[$ref:1,2] vM/LVINTRO ->4
4     <;> nextstate(main 2 -e:1) v:{ ->5
d     <2> aassign[t4] vKS/COMMON ->e
-        <1> ex-list lK ->a
5           <0> pushmark s ->6
9           <@> sort lK ->a
6              <0> pushmark s ->7
8              <1> rv2av[t3] lK/1 ->9
7                 <0> padsv[$ref:1,2] s ->8
-        <1> ex-list lK ->d
a           <0> pushmark s ->b
c           <1> rv2av[t2] lKRM*/1 ->d
b              <0> padsv[$ref:1,2] sM/DREFAV ->c
-e syntax OK
让我们使用
-MO=concurrence
选项查看引擎盖下面。首先,我们进行正常的就地排序,以查看预期结果:

$ perl -E'say $^V'
v5.18.2
$ perl -MO=Concise -e'my @arr; @arr = sort @arr'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
3     <0> padav[@arr:1,2] vM/LVINTRO ->4
4     <;> nextstate(main 2 -e:1) v:{ ->5
-     <1> ex-aassign vKS/64 ->8
-        <1> ex-list lK ->-
5           <0> pushmark s ->6
7           <@> sort lK/INPLACE ->8
6              <0> padrange[@arr:1,2] l/1 ->7
-              <0> padav[@arr:1,2] lRM* ->7
-        <1> ex-list lK ->-
-           <0> ex-pushmark s ->-
-           <0> ex-padav lRM* ->-
-e syntax OK
$perl-E'say$^V'
v5.18.2
$perl-MO=简明-e'my@arr@arr=排序@arr'
8离开[1参考]vKP/REFC->(结束)
1输入->2
2下一状态(主1-e:1)v:{->3
3 padav[@arr:1,2]vM/LVINTRO->4
4下一状态(主2-e:1)v:{->5
-ex-aassign vKS/64->8
-前列表lK->-
5推动标记s->6
7分类lK/就地->8
6焊盘范围[@arr:1,2]l/1->7
-padav[@arr:1,2]lRM*->7
-前列表lK->-
-ex pushmark s->-
-前padav lRM*->-
-e语法正常
有趣的是:
sort lK/INPLACE->8
,它似乎可以进行适当的排序。现在让我们对引用执行相同的操作:

$ perl -MO=Concise -e'my $ref; @$ref = sort @$ref'
e  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
3     <0> padsv[$ref:1,2] vM/LVINTRO ->4
4     <;> nextstate(main 2 -e:1) v:{ ->5
d     <2> aassign[t4] vKS/COMMON ->e
-        <1> ex-list lK ->a
5           <0> pushmark s ->6
9           <@> sort lK ->a
6              <0> pushmark s ->7
8              <1> rv2av[t3] lK/1 ->9
7                 <0> padsv[$ref:1,2] s ->8
-        <1> ex-list lK ->d
a           <0> pushmark s ->b
c           <1> rv2av[t2] lKRM*/1 ->d
b              <0> padsv[$ref:1,2] sM/DREFAV ->c
-e syntax OK
$perl-MO=简明-e'my$ref;@$ref=sort@$ref'
e离开[1参考]vKP/REFC->(结束)
1输入->2
2下一状态(主1-e:1)v:{->3
3 padsv[$ref:1,2]vM/LVINTRO->4
4下一状态(主2-e:1)v:{->5
d设计[t4]vKS/普通->e
-前列表lK->a
5推动标记s->6
9排序lK->a
6推动标记s->7
8 rv2av[t3]lK/1->9
7 padsv[$ref:1,2]s->8
-前列表lK->d
a推动标记s->b
c rv2av[t2]lKRM*/1->d
b padsv[$ref:1,2]sM/DREFAV->c
-e语法正常
我在
sort lK->a
中没有看到就地标志。因此,优化似乎只在使用相同变量时有效,而在使用相同数组时无效。但这意味着,如果我们将数组变量别名为某个标量引用的数组(使用):

perl-MData::Alias-MO=concurrence-e'my$ref;Alias my@arr=@$ref;@arr=sort@arr'
e离开[1参考]vKP/REFC->(结束)
1输入->2
2下一状态(主1-e:1)v:{->3
3 padsv[$ref:1,3]vM/LVINTRO->4
4下一状态(主2-e:1)v:{->5
-输入子vKS/INARGS->a
...
a下一状态(主3-e:1)v:{->b
-ex-aassign vKS/64->e
-前列表lK->-
b推动标记s->c
d分类lK/就地->e
c焊盘范围[@arr:2,3]l/1->d
-padav[@arr:2,3]lRM*->d
-前列表lK->-
-ex pushmark s->-
-前padav lRM*->-
-e语法正常
…并且原地标志再次出现
排序lK/inplace->e
:-)


这意味着这是不正确的。

你知道排序a使用的算法是什么吗??我假设第二个链接可能会给出某种答案,但目前没有时间阅读差异:(@DVK=>据我所知,它正在使用就地合并排序。优化发生在
sortsv
的包装中,因此perl似乎总是进行就地排序,但通常是在副本上进行的。@DVK我从阅读代码中相信,除非在构建perl时另有指定,否则它将默认使用mergesort。合并排序和快速排序是这两个都在代码中实现。感谢
之后的澄清,您应该能够编写
!虽然存在就地优化,但它仅在参数和左值是相同的数组变量时才应用。从perl 5.18.2开始,它不应用于引用–请参阅。提示:
-MO=简明,-exec
显示在
exec
顺序,但也隐藏已优化的操作码(第一列中带有
-
),以便更容易阅读。FYI:从FYI合并:从
perl -MData::Alias -MO=Concise -e'my $ref; alias my @arr = @$ref; @arr = sort @arr'
e  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
3     <0> padsv[$ref:1,3] vM/LVINTRO ->4
4     <;> nextstate(main 2 -e:1) v:{ ->5
-     <1> entersub vKS/INARGS ->a
         ...
a     <;> nextstate(main 3 -e:1) v:{ ->b
-     <1> ex-aassign vKS/64 ->e
-        <1> ex-list lK ->-
b           <0> pushmark s ->c
d           <@> sort lK/INPLACE ->e
c              <0> padrange[@arr:2,3] l/1 ->d
-              <0> padav[@arr:2,3] lRM* ->d
-        <1> ex-list lK ->-
-           <0> ex-pushmark s ->-
-           <0> ex-padav lRM* ->-
-e syntax OK