Perl中的默认排序在数组上排序是什么?

时间:2017-03-06 18:41:55

标签: perl sorting

我正在阅读一些对哈希数组进行排序的Perl代码

uniq sort @{$ProjectData{$project}{Packages}}

我不清楚这是否按哈希的键,哈希的键+值或哈希的内存地址进行排序。另外,我还不清楚uniq是否稳定。我将编写自己的比较功能,但它似乎或按原样运行,所以如果有人能够清理当前正在发生的事情,我会很感激。

3 个答案:

答案 0 :(得分:1)

如果$ProjectData{$project}{Packages}是对散列引用数组的引用,那么Perl会将所有这些引用字符串化为HASH(0xf1f6d290),并将它们排序为字符串

有效的是它按内存地址排序,但这真的不是很有用,你也可以放弃sort,留下你的

uniq @{ $ProjectData{$project}{Packages} }

如果你正在使用List::Util::uniq那么它是稳定的,但除非你通过更有用的东西对数据进行排序,否则它无关紧要

答案 1 :(得分:0)

sort对在堆栈 [1] 上传入的标量进行排序。在您的情况下,放置在堆栈上的标量是$ProjectData{$project}{Packages}引用的数组的元素。

默认比较功能按升序词汇顺序对值进行排序。

 sort LIST

的缩写
 sort { $a cmp $b } LIST

这意味着要比较的元素是字符串化的,并逐个字符地进行比较。这会在abc之前对def进行排序,在123之前对13进行排序。

但是你要比较引用的字符串化。以下是引用的字符串化示例:

$ perl -E'say {}'
HASH(0x1a36ff8)

$ perl -E'say bless({}, "SomeClass");'
SomeClass=HASH(0x41d0a28)

正如你可以推测的那样,sort在给定引用时唯一可以依赖的是将相同的引用放在一起。它不会将对相同哈希的引用放在一起,只引用相同的哈希值。

来自List :: MoreUtils的

uniq是稳定的。

  

返回列表中元素的顺序与LIST中的相同。

它还使用了标量的词法比较。这意味着它只会删除对相同哈希的引用,而不是对相同哈希的引用。

$ perl -MData::Dumper=Dumper -MList::MoreUtils=uniq -e'
   my $x = { a => 234, b => 345 };
   my $y = $x;
   my $z = { a => 234, b => 345 };
   print(Dumper([ uniq $x, $y, $z ]));
'
$VAR1 = [
          {
            'b' => 345,
            'a' => 234
          },
          {
            'b' => 345,
            'a' => 234
          }
        ];

提示:除非您使用删除需要排序输入的重复项的方法,否则在排序值之前删除重复项更有意义。

sort +uniq @{$ProjectData{$project}{Packages}}

+阻止uniq被用作sort的比较功能。)

但是,由于sort在给定引用时将有意义地完成,所以uniq将相同的引用放在一起,并且因为uniq @{$ProjectData{$project}{Packages}} 已经删除了相同的引用,所以上面的内容可以简化为

use JSON::XS qw( );

my $json_serializer = JSON::XS->new->canonical;

my %seen;
my @uniques = grep !$seen{ $json_serializer->encode($_) }++, @references;

您更有可能希望过滤掉对重复哈希的引用,而不是对同一哈希的引用。以下是如何做到这一点:

$ perl -MData::Dumper=Dumper -MJSON::XS -e'
   my $json_serializer = JSON::XS->new->canonical;
   my $x = { a => 234, b => 345 };
   my $y = $x;
   my $z = { a => 234, b => 345 };
   my %seen;
   print(Dumper([ grep !$seen{ $json_serializer->encode($_) }++, $x, $y, $z ]));
'
$VAR1 = [
          {
            'b' => 345,
            'a' => 234
          }
        ];

例如,

downloadResultsFile() {

 fetch(`https://XXXXXXXX/api/download-results-file?jobName=${this.props.selectedRun.jobs[0].env.MIC_JOB_ID}`, {
  origin: 'same-origin', 
})
.then((res) => res.blob())
.then((file) =>  FileSaver.saveAs(file, this.props.selectedRun.jobs[0].env.MIC_JOB_ID + '-results.zip'));   


}
  1. 好的,从技术上讲,它实际上可以作为优化传递一个数组,但这是内部细节。

答案 2 :(得分:0)

至于sort @{$ProjectData{$project}{Packages}},它只是使用默认排序对数组@{$ProjectData{$project}{Packages}}的内容进行排序。

根据它使用的文档"标准字符串比较顺序"这意味着它使用cmp。这意味着它通过将参数转换为字符串并在 中按字符编码 中出现的顺序一次比较一个字符来进行排序。我们过去称之为#34; ASCIIbetical"但现在使用UTF-8,它不一定是ASCII。

一些例子。

# 1, 20, 3 because it considers them "1", "20", "3".
sort 1, 3, 20;

# a, z
sort "z", "a";

# Z, a because ASCII Z is 90 and ASCII a is 97.
sort "Z", "a";

# z, ä because UTF-8 z is 122 and UTF-8 ä is 195 164
use utf8;
sort "z", "ä";