这个Perl语法构造是什么?

时间:2014-08-11 14:40:52

标签: perl sorting syntax

我在之前的帖子Sorting file names by numeric value中有一个跟进问题。

解决方案就是这段代码:

opendir(XMLDIR,$xmldirname);
my @files = sort {substr($a, 0, index($a, '.')) <=> substr($b, 0, index($b, '.'))} readdir(XMLDIR);

我真的不明白readdir前面的整个排序{...}正在做什么,或者更确切地说,它是如何做它正在做的事情。当然,我可以看到两个值相互比较。但是整个事情是什么样的语法结构? $ a和$ b来自哪里?我可以在Perl书中看到哪些标题?这是一个特殊的东西,只适用于sort {},还是有其他方法可以使用这个构造?

5 个答案:

答案 0 :(得分:7)

sort采用的语法是

sort BLOCK LIST

LIST表示的表达式是返回要排序的值列表。在您的情况下,这是readdir(XMLDIR)。它返回目录中文件名的列表。

BLOCK是有趣的部分。它代表curlies中的代码,由排序算法调用以与要排序的元素进行比较。要比较的元素以$a$b提供,代码应评估为以下之一:

  • 如果$a应放在$b之前
  • ,则为负值
  • 如果相对于$a放置$b
  • 的问题并不重要,则为零
  • 如果$a之后应放置$b,则为正值。

substr($a, 0, index($a, '.'))在第一个.之前提取文件名的一部分。在这种情况下,它会提取文件名中的数字。

然后,从<=>数字比较从两个文件名中提取的数字,如上所述重新调整-10+1


请注意,您的代码会发出警告,因为它没有考虑readdir将返回...。我通过在原始问题中添加answer来解决此问题。

答案 1 :(得分:5)

这是使用sort参数调用block。块包含在其他几个Perl内置文件中,包括mapgrep

块参数是一种为要执行的函数定义自己的代码的方法。 sort使用该块比较要排序的列表中的两个值,由$a$b表示。

使用prototypes,您可以定义自己的子程序以类似的方式工作:

sub block_exec(&@) {
    my $block = shift;

    for (@_) {
        &$block;
    }
}

block_exec { print "block! $_\n"; } (1..10);

答案 2 :(得分:1)

在哪个标题下,我可以在Perl书中看到它?

在&#39;排序&#39;

http://perldoc.perl.org/functions/sort.html

该行定义了一种比较两个值(用于创建排序列表)的自定义方法,该方法与默认比较不同。 $ a和$ b是排序中一次比较的两个值。

答案 3 :(得分:1)

$a$bsort提供给传递给它的比较函数。 sort作用于数组,该数组在此实例中由readdir生成。 sort重复将未命名的比较例程应用于数组中的条目,重新排列它们直到它们按顺序排列。

答案 4 :(得分:1)

这样做:排序@arrayofnumbers
与:{$ a cmp $ b} @arrayofnumbers

相同

其中$ a和$ b是在排序的每个步骤中比较的两个项目。 代码块的返回值需要是一个整数,其中0表示项目相同,&lt; 0表示$ a小于$ b,&gt; 0表示$ a大于$ b。通常用字符串的“cmp”和&lt; =&gt;来完成。数字。

所以令你困惑的部分,大括号之间的东西,实际上只是一个代码块,它将返回-1,0或+1,具体取决于你想要比较两个项目的方式。

你可以在那里做很多事情,例如你可以通过这样的方式看到比较的顺序:

sort { print "$a cmp $b = ".($a cmp $b)."\n"; return $a cmp $b } (2,19,29,39);

产量:
2 cmp 19 = 1
29 cmp 39 = -1
19 cmp 29 = -1
29 cmp 2 = 1

让人们知道的一件事是默认比较是字符串比较。 所以如果你这样做:

print join(',', sort 2,19,39,29)."\n";

你会得到:19,2,29,39

要进行整数比较,您需要这样做:

sort { $a <=> $b } (2,19,39,29)

相关问题