我刚开始学习Perl,因此我的问题可能看起来很愚蠢。我提前道歉。根据每行上第一个元素的数值对行进行排序?
我有一个列表说@data
其中包含从输入中读取的行列表。这些行包含由(未知数量)空格分隔的数字。
现在,我想对它们进行分类并打印出来,但不是按照字典顺序排列,而是按照出现在行上的第一个数字的数字值。
我知道这一定很简单,但我不知道该怎么做?
由于提前,
我刚开始学习Perl,因此我的问题可能看起来很愚蠢。我提前道歉。根据每行上第一个元素的数值对行进行排序?
我有一个列表说@data
其中包含从输入中读取的行列表。这些行包含由(未知数量)空格分隔的数字。
现在,我想对它们进行分类并打印出来,但不是按照字典顺序排列,而是按照出现在行上的第一个数字的数字值。
我知道这一定很简单,但我不知道该怎么做?
由于提前,
您可以使用一个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
但你可以看到,它已经正确排序。我不会建议这个解决方案,但我认为这是一个很好的演示。
非常感谢您的完整解释。我尝试了上面的内容,但是用'@ data'替换了'',这是一个包含我的行的列表。虽然我收到以下错误:'在数字比较(<=>)处使用未初始化的值。/ mergedata line 53,<> line 20.' – PBM
@ManiBastaniParizi这是因为你的数组中有一个未定义的值。如果你想检查你的数据,试试'使用Data :: Dumper;打印Dumper \ @data;' – TLP
@ManiBastaniParizi哦,对,你说你可以有负面的价值...然后你需要一个不同的正则表达式,我会编辑来解决这个问题。 – TLP