我有这组代码:
use strict;
use warnings;
my %hash = ( 5328 => 'Adorable',
26191 => '"Giraffe"',
57491 => 'Is Very',
4915 => 'Cute',);
foreach (sort { ($hash{$a} cmp $hash{$b}) || ($a cmp $b) } keys %hash)
{ print "$hash{$_}\n"; }
这将导致:
"Giraffe"
Adorable
Cute
Is Very
我需要按字母顺序排序,并忽略AlphaNumeric字符之前的特殊字符,如下例所示:
Adorable
Cute
"Giraffe"
Is Very
有什么建议吗?
答案 0 :(得分:7)
您可以简单地执行(请注意,我已将第二个cmp
更改为穿梭运算符<=>
以获取数值):
foreach (sort { ($hash{$a}=~s/^\W+//r cmp $hash{$b}=~s/^\W+//r) || ($a <=> $b) } keys %hash) {
print "$hash{$_}\n";
}
但如果你有大量数据,那么转换数据(一劳永逸)会更好: 例如,使用schwartzian变换:
my @result = map { $_->[2] }
sort { ($a->[0] cmp $b->[0]) || ($a->[1] <=> $b->[1]) }
map { [ $hash{$_}=~s/^"|"$//gr, $_, $hash{$_}] } keys %hash;
print join "\n", @result;
答案 1 :(得分:5)
创建一个截断特殊字符的函数(在我的例子中为truncate_special_chars
)。然后,在sort
例程下使用它。
use strict;
use warnings;
my %hash = (
5328 => 'Adorable',
26191 => '"Giraffe"',
57491 => 'Is Very',
4915 => 'Cute',
);
print join "\n",
map { $hash{$_ -> [0]} }
sort { $a -> [1] cmp $b -> [1] || $a -> [0] <=> $b -> [0] }
map { [ $_, truncate_special_chars($hash{$_}) ] }
keys %hash;
sub truncate_special_chars {
my $str = shift;
$str =~ s/^\W//;
# may be use lc if you want case insensitive sort
return $str;
}
否则,如果您使用/r
,则可以使用Perl >= 5.14
。
答案 2 :(得分:2)
使用自定义排序功能去除您要忽略的字符。
foreach (sort {
my ($aa,$bb) = ($hash{$a},$hash{$b});
s/["]//g for $aa,$bb; # ignore " char. Add whatever else you want
$aa cmp $bb # or lc($aa) cmp lc($bb) case-insensitive search
|| $a cmp $b
} keys %hash) { ... }
答案 3 :(得分:2)
尝试以下
use strict;
use warnings;
my %hash = ( 5328 => 'Adorable',
26191 => '"Giraffe"',
57491 => 'Is Very',
4915 => 'Cute',);
foreach (sort{my ($one)=$hash{$a}=~m/([\w\s]+)/; my ($two)=$hash{$b}=~m/([\w\s]+)/; $one cmp $two} keys %hash)
{
print "$hash{$_}\n";
}
将元素分组并存储到$one
和$two
,然后进行比较。
但@Casimir et Hippolyte答案很容易。他使用non-destructive modifier(r).但它将支持5.14版本以上