我今天开始学习Perl并发现this非常有趣的教程。 但是,对于我的生活,我无法绕过这段代码。
print " $_: $created{$_}" for(sort({$created{$b} <=> $created{$a}} keys %created));
这是什么类型的?更具体地说,变量$a
和$b
是什么?
我尝试了documentation,但不能说它有所帮助。任何支持将不胜感激。
答案 0 :(得分:9)
这里有一些事情要发生。首先,我将解决后缀循环;
say $_ for ('foo', 'bar', 'baz');
在语义上与执行此操作相同
for ('foo', 'bar', 'baz') { say $_ }
现在进行排序。默认情况下,Perl的sort
按字母顺序排序
sort (20, 3, 100); # RESULT: (100, 20, 3)
Perl提供了一种按字母顺序(cmp
)或数字(<=>
)明确比较的方法。
20 cmp 3; # RESULT: -1 (means: Less)
20 <=> 3; # RESULT: 1 (means: More)
20 <=> 20; # RESULT: 0 (means: Same)
所以你可以在sort
块中使用这些运算符,但是你把它放在运算符的哪一边?这是特殊$a
和$b
变量的来源。
sort { $a <=> $b } (20, 3, 100); # RESULT: (3, 20, 100)
这也是您不应该为$a
或$b
手动分配值的原因,因为如果您这样做,sort
将无法正常运行!
所以把所有这些放在一起,你的排序是按照相应的值以数字方式对Hash的键进行排序
my %hash = ( twenty => 20, three => 3, onehundred => 100 );
for ( sort { $hash{$a} <=> $hash{$b} } keys %hash ) {
say "$_: %hash{$_}"
}
输出
three: 3
twenty: 20
onehundred: 100
您也可以{ $b <=> $a }
进行反向排序。
如果这一切看起来晦涩难懂,那就有点儿了。我建议您使用像Sort::Key
这样的模块来满足您的大部分排序需求......或者如果您更喜欢Sort::Naturally
,那么可能会。
答案 1 :(得分:5)
print " $_: $created{$_}"
for ( sort { created{$b} <=> $created{$a} } keys %created );
这使用了for
的修复后形式。在Perl中,for
和foreach
是相同的。两者都可以与C风格的for
语法以及较短的foreach
样式语法一起使用。
我们可以将此循环重写为以下更详细的版本。
foreach ( sort { created{$b} <=> $created{$a} } keys %created ) {
print " $_: $created{$_}";
}
接下来,让我们看一下$_
。它被称为主题,如果没有给出其他变量,它将被用作Perl中很多东西的默认输入。在foreach
循环中,如果没有使用迭代变量,则括号中列表的每个元素都以$_
结尾。同样,为了清楚起见,可以重写。
foreach my $elem ( sort { created{$b} <=> $created{$a} } keys %created ) {
print " $elem: $created{$elem}";
}
现在让我们看一下sort
。两个变量$a
和$b
是Perl中始终存在的全局变量。它们保留在sort
语句后面的块中。
sort { BLOCK } LIST
$a
和$b
包含列表中的两个值,这些值在块中进行比较。该块的行为类似于匿名函数(在其他语言中称为 lambda ),并且后面没有逗号。或者,您可以将名称sub的名称作为带有引号的裸字放在那里。再说一遍,没有逗号。
sub bubbly_sort { $a <=> $b }
sort bubbly_sort 3, 2, 1;
<=>
运算符进行数值比较。它会比较这两个值并返回-1
,0
或1
。
sort { $b <=> $a } LIST
这将对LIST中的值进行数字降序排序,因此最高值首先出现。 $a <=> $b
会升序。
sort { created{$b} <=> $created{$a} } keys %created
keys
关键字为您提供散列%created
内的密钥的无序列表。 sort
中的块比较%created
哈希中这些键后面的值,并对键降序进行排序。所以你得到一个排序键列表。
其余代码只打印出该排序键列表的键/值列表。
值得注意的是,输出全部在一行上,因为print
之后没有换行符。
您发布的精简版本比我在此答案中显示的长版本更具可读性。但它有适当的缩进和使用括号,它会立即下降。
print " $_: $created{$_}"
for sort { created{$b} <=> $created{$a} } keys %created;
与
print " $_: $created{$_}" for(sort({$created{$b} <=> $created{$a}} keys %created));
与
foreach ( sort { created{$b} <=> $created{$a} } keys %created ) {
print " $_: $created{$_}";
}
在我看来,第一个版本读起来最像英语句子,这很好。干净,可读的代码应始终是优秀开发人员的首要任务。
答案 2 :(得分:3)
打破它。
这是排序位:
sort({$created{$b} <=> $created{$a}} keys %created)
括号与此无关。
sort { $created{$b} <=> $created{$a} } keys %created
所以这是一种非常标准的排序。
sort
是sort。
第一个参数是一个块......
如果指定了SUBNAME,则它会给出一个子例程的名称,该子例程返回一个小于,等于或大于0的整数,具体取决于列表元素的排序方式。 (&lt; =&gt;和cmp运算符在此类例程中非常有用。)SUBNAME可以是标量变量名(unsubscripted),在这种情况下,该值提供要使用的实际子例程的名称(或引用)。您可以使用BLOCK作为匿名的内联排序子例程来代替SUBNAME。
第二个参数是被排序的东西(keys %created
)。即哈希中keys的列表。
在子资源中,$a
和$b
是要排序的元素。因此$created{$b} <=> $created{$a}
获取密钥并比较散列中与它们关联的值。
因此,sort会输出哈希中的键列表,并按与之关联的值进行排序。
然后传递给后缀for
,因此对于每个键,它都会执行某些操作(按值的顺序)。
东西是print " $_: $created{$_}"
:所以它打印键,然后是冒号,然后是值。