在 Perl 中排序名称列表

Sorting list of names in Perl

我正在尝试学习 Perl,我对它还很陌生,可能不到一周。

我想对名称列表(在本例中为水果)进行排序,并给它们一个 ID。我的脚本目前为它们提供了 ID,但我也想对它们进行排序。

当前代码:

use strict;
use warnings;

my %unique;

open(my $inFile, $ARGV[0]) || die "Could not open file '$ARGV[0]' $!";
open(my $outFile, ">$ARGV[1]") || die "Could not find file '>$ARGV[1]' $!";

while (<$inFile>) {
        my @fields = split;

        my $fruit  = $fields[0];
        my $quantity   = $fields[1];

        my @parts = split(/[_.]/, $fruit);
        my $counter = ++$unique{$parts[1]}{$parts[2]};

        print $outFile join("\t", $fruit, $quantity, "$fruit.$counter"), "\n";
}

输入:

Apple   3
Apple   50
Apple   1
Orange  51
Orange  21

当前输出:

Apple   3   Apple.1
Apple   50  Apple.2
Apple   1   Apple.3
Orange  51  Orange.1
Orange  21  Orange.2

想要的输出:

Apple   1   Apple.1
Apple   3   Apple.2
Apple   50  Apple.3
Orange  21  Orange.1
Orange  51  Orange.2

Apple   3   Apple.2
Apple   50  Apple.3
Apple   1   Apple.1
Orange  51  Orange.2
Orange  21  Orange.1

谢谢

更新:

新输入:

Apple   3   1
Apple   50  2
Apple   1   3
Orange  51  3
Orange  21  5

想要输出

Apple   1   3   Apple.1
Apple   3   1   Apple.2
Apple   50  2   Apple.3
Orange  21  5   Orange.1
Orange  51  3   Orange.2
# Read in the data
my @data;
while (<>) {
   chomp;
   push @data, [ split(/\t/, $_, -1) ];
}

# Sort it
@data = sort {
   $a->[0] cmp $b->[0]   # By name
      ||
   $a->[1] <=> $b->[1]   # By quantity
} @data;

# Generate the ids and output the data.
my %counts;
for my $row (@data) {
   my $id = join('.', $row->[0], ++$counts{ $row->[0] });
   push @$row, $id;
   print(join("\t", @$row), "\n");
}

这是一个使用几个 CPAN 模块 (Sort::Key::Multi and DDP) 的解决方案。

#!perl -l
use Sort::Key::Multi 'sii_keysort' ;

my @mungeddata = sii_keysort { chomp ; split /\s+/ , $_ }  <DATA> ;

use DDP;
p @mungeddata ;

__DATA__
Apple    3    1
Apple    50   2
Apple    1    3
Orange   51   3
Orange   21   5

输出:

[
    [0] "Apple    1    3",
    [1] "Apple    3    1",
    [2] "Apple    50   2",
    [3] "Orange   21   5",
    [4] "Orange   51   3"
] 

试试这个

# Read in the data
my @data;
while (<>) {
   chomp;
   push @data, [ split(/\t/, $_, -1) ];
}

# Sort it
@data = sort {
   $a->[0] cmp $b->[0]   # By name
      ||
   $a->[1] <=> $b->[1]   # By quantity
} @data;

# Generate the ids and output the data.
my %counts;
for my $row (@data) {
   my $id = join('.', $row->[0], ++$counts{ $row->[0] });
   push @$row, $id;
   print(join("\t", @$row), "\n");
}