【问题标题】:Sorting lines according to the numerical value of the first element on each line?根据每行第一个元素的数值对行进行排序?
【发布时间】:2013-10-11 19:16:36
【问题描述】:

我刚刚开始学习 Perl,因此我的问题可能看起来很愚蠢。我提前道歉。

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

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

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

提前致谢,

【问题讨论】:

    标签: perl sorting


    【解决方案1】:

    您可以使用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
    

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

    但如您所见,它已正确排序。我不会建议这个解决方案,但我认为在这种情况下这是一个很好的演示。

    【讨论】:

    • 非常感谢您的完整解释。我尝试了上述方法,但只是将&lt;DATA&gt; 替换为@data,这是一个包含我的行的列表。我收到以下错误:Use of uninitialized value in numeric comparison (&lt;=&gt;) at ./mergedata line 53, &lt;&gt; line 20.
    • @ManiBastaniParizi 那是因为你的数组中有一个未定义的值。如果你想检查你的数据,试试use Data::Dumper; print Dumper \@data;
    • @ManiBastaniParizi 哦,对了,你说你可以有负值......那么你需要一个不同的正则表达式,我会编辑来解决这个问题。
    • 我想这是因为数字是实数。其中一些可能以- 开头并且可以包含浮点数。所以我想我应该改变正则表达式。我说的对吗?
    • @ManiBastaniParizi 是的.. 使用\S+ 进行捕获可能是最简单的,假设所有非空格都有有效的数字字符。
    【解决方案2】:

    你可以使用排序功能:

    @sorted_data = sort(@data);
    

    【讨论】:

    • 这不会执行所要求的操作,因为它是按词法排序而不是按要求按数字排序。
    • 谢谢,但这将按字典顺序对它们进行排序,例如 -1 将出现在 -2 之前。我希望它们按数字顺序排序。
    • -1。你试过了吗?这会将10 放在2 之前。
    猜你喜欢
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多