Steve Blenheim:239-923-7366:238-934-7865:95 Latham Lane, Easton, PA 83755:11/12/56:20300
Betty Boop:245-836-8357:245-876-7656:635 Cutesy Lane, Hollywood, CA 91464:6/23/23:14500
Igor Chevsky:385-375-8395:385-333-8976:3567 Populus Place, Caldwell, NJ 23875:6/18/68:23400
Norma Corder:397-857-2735:397-857-7651:74 Pine Street, Dearborn, MI 23874:3/28/45:245700
我正在尝试从第二个单词(姓氏)按反向字母顺序对文本进行排序,但却无法找到如何执行此操作。我这样做是从文件中读取的
open (FILE, phonebook);
@line = <FILE>;
close(FILE);
任何想法?我可以按字母顺序排序第一个字段并反转,但似乎无法让第二个字段正确排序。 提前致谢
答案 0 :(得分:10)
我同意tadmc的担心,即第二个字段,通过空格并不总是姓氏,但回答问题,因为它与第二个字段有关,你可以使用split
得到它,你可以这样排序:
简单但非常慢的版本(易于阅读,但每次比较两行时重新拆分每个字段,效率很低)。
@lines = sort { # Compare second fields
(split " ", $a)[1]
cmp
(split " ", $b)[1]
} @lines;
Schwartzian transform版本(与前一版完全相同,只是更快):
@lines = map { # Get original line back
$_->[0]
} sort { # Compare second fields
$a->[1] cmp $b->[1]
} map { # Turn each line into [original line, second field]
[ $_, (split " ", $_)[1] ]
} @lines;
答案 1 :(得分:2)
如果您不介意使用shell,sort -r -k2
将按相反顺序对文件进行排序。
答案 2 :(得分:2)
根据Miguel Prz解决方案,我将'cmd'替换为'&lt; =&gt;'。 这对数字很重要。如果使用CMP,那么排序将作为字符串(数字)工作 - 第一个字符是最重要的,然后是第二个,依此类推。如果您有数字:607,8和35,那么CMP会将其排序为:8,607,35。要将其排序为数字,我们使用“&lt; =&gt;”方法和结果将是:607,35,8
use strict;
open my $FILE, '<', 'phonebook';
my @lines = <$FILE>;
my @sorted = sort {
my @a = split(/\s+/,$a);
my @b = split(/\s+/,$b);
$b[1] <=> $a[1] } @lines;
foreach my $item(@sorted) {
print "$item\n";
}
close $FILE;
答案 3 :(得分:0)
您需要逐行读取文件才能执行此操作。像这样:
my %list;
open(FILE, phonebook);
while(<FILE>){
my @vals = split(/:/, $_);
(my $key = $vals[0]) =~ s/(\S+)\s+(.+)/$2 $1/; # split first field, reverse word order
$list{$key} = $_; #save row keyed on $key
}
foreach my $key(sort {$b cmp $a} keys(%list)){
print $list{$key};
}
答案 4 :(得分:0)
我认为以Modern Perl方式编写它是有趣的(解决方案是相同的),这是完整的脚本:
use strict;
open my $FILE, '<', 'phonebook';
my @lines = <$FILE>;
my @sorted = sort {
my @a = split(/\s+/,$a);
my @b = split(/\s+/,$b);
$b[1] cmp $a[1] } @lines;
foreach my $item(@sorted) {
print "$item\n";
}
close $FILE;
答案 5 :(得分:0)
我很惊讶没有人提到这一点,但如果我们正在对电话簿进行排序,我们可能并不真正想要纯ASCII排序。
Bob DeCarlo
之前真的属于Ralph Dearborn
吗?如果您使用cmp
排序,DeCarlo先生将在结果中排在第一位。
即使你对案例进行了规范化,你仍然会遇到问题。排序和归档有很多并发症。这些问题的organizations have rules不同handling。
由于排序是一项昂贵的操作,因此您需要尽可能快地进行每次比较。这样做的方法是使用最简单的代码进行所有比较。由于cmp
本身不会为我们提供所需的结果,因此我们需要为电话簿中的每个项目生成并缓存标准化的排序术语。
因此,假设您已经在阵列中获得了电话簿数据:
sub extract_and_normalize {
# Do stuff here to embody your alphabetization rules.
return [ $normed, $line ];
}
# Generate your sort terms
my @processed = map extract_and_normalize($_), @lines;
# Sort by the normalized values
my @sorted = sort {$a->[0] cmp $b->[0]}, @processed;
# Extract the lines from the sorted set.
@lines = map $_->[1], @sorted;
或者像hobbs
建议的那样使用Schwartzian变换来避免产生所有中间变量:
@lines = map $_->[1],
sort { $a->[0] cmp $b->[0] }
map extract_and_normalize($_), @lines;