2013-10-11 76 views
0

我刚开始学习Perl,因此我的问题可能看起来很愚蠢。我提前道歉。根据每行上第一个元素的数值对行进行排序?

我有一个列表说@data其中包含从输入中读取的行列表。这些行包含由(未知数量)空格分隔的数字。

现在,我想对它们进行分类并打印出来,但不是按照字典顺序排列,而是按照出现在行上的第一个数字的数字值。

我知道这一定很简单,但我不知道该怎么做?

由于提前,

回答

6

您可以使用一个Schwartzian transform,用正则表达式

use strict; 
use warnings; 

my @sorted = map $_->[0], 
       sort { $a->[1] <=> $b->[1] } 
       map { [ $_, /^(-?[\d.]+)/ ] } <DATA>; 
print @sorted; 

__DATA__ 
21 13 14 
0 1 2 
32 0 4 
11 2 3 
1 3 3 

捕捉行中的第一个数字输出:

0  1  2 
1  3  3 
11  2  3 
21  13  14 
32  0  4 

从后面读取变换,<DATA>是我们使用的文件句柄,它将返回文件中行的列表。第一个map语句返回一个数组引用[ ... ],它包含原始行,以及行中捕获的第一个数字。或者,您可以在这里使用正则表达式/^(\S+)/来捕获任何非空白字符。在比较行时,排序会在数组ref中使用此捕获的数字。最后,最后的map将数组ref转换回存储在$_->[0]中的原始值。

请注意,这依赖于在行首有数字的行。如果这可能会丢失或空白,则会产生一些无法预料的后果。只用简单的数字排序也将“工作”,因为Perl将转换您的线为正确的数字之一,假设每行


注始于一个数字后面的空间。您将会收到一些警告,如Argument "21 13 14\n" isn't numeric in sort。例如,如果我代替我上面的代码与

my @foo = sort { $a <=> $b } <DATA>; 

我会得到输出:

Argument "21 13  14\n" isn't numeric in sort at foo.pl line 6, <DATA> line 5. 
Argument "0  1  2\n" isn't numeric in sort at foo.pl line 6, <DATA> line 5. 
Argument "32 0  4\n" isn't numeric in sort at foo.pl line 6, <DATA> line 5. 
Argument "11 2  3\n" isn't numeric in sort at foo.pl line 6, <DATA> line 5. 
Argument "1  3  3\n" isn't numeric in sort at foo.pl line 6, <DATA> line 5. 
0  1  2 
1  3  3 
11  2  3 
21  13  14 
32  0  4 

但你可以看到,它已经正确排序。我不会建议这个解决方案,但我认为这是一个很好的演示。

+0

非常感谢您的完整解释。我尝试了上面的内容,但是用'@ data'替换了'',这是一个包含我的行的列表。虽然我收到以下错误:'在数字比较(<=>)处使用未初始化的值。/ mergedata line 53,<> line 20.' – PBM

+0

@ManiBastaniParizi这是因为你的数组中有一个未定义的值。如果你想检查你的数据,试试'使用Data :: Dumper;打印Dumper \ @data;' – TLP

+0

@ManiBastaniParizi哦,对,你说你可以有负面的价值...然后你需要一个不同的正则表达式,我会编辑来解决这个问题。 – TLP

-1

您可以使用排序功能:

@sorted_data = sort(@data); 
+0

这不会做所要求的,因为它按字面排序而不是数字按要求排序。 – dgw

+0

谢谢,但这会按字典顺序对它们进行排序,例如-1会在-2之前出现。我希望他们按数字顺序排序。 – PBM

+0

-1。你试过了吗?这会在'2'之前放置'10'。 – Toto

相关问题