Est*_*ten 3 sorting methods perl inheritance subroutine
我从未使用过Perl,但我需要完成这个练习.我的任务是以几种不同的方式对数组进行排序.我已经获得了测试脚本.此脚本将数组和打印语句放在一起,用于排序的每个阶段.我把它命名为foo.pl:
use strict;
use warnings;
use MyIxHash;
my %myhash;
my $t = tie(%myhash, "MyIxHash", 'a' => 1, 'abe' => 2, 'cat'=>'3');
$myhash{b} = 4;
$myhash{da} = 5;
$myhash{bob} = 6;
print join(", ", map { "$_ => $myhash{$_}" } keys %myhash) . " are the starting key => val pairs\n";
$t->SortByKey; # sort alphabetically
print join(", ", map { "$_ => $myhash{$_}" } keys %myhash) . " are the alphabetized key => val pairs\n";
$t->SortKeyByFunc(sub {my ($a, $b) = @_; return ($b cmp $a)}); # sort alphabetically in reverse order
print join(", ", map { "$_ => $myhash{$_}" } keys %myhash) . " are the reverse alphabetized key => val pairs\n";
$t->SortKeyByFunc(\&abcByLength); # use abcByLength to sort
print join(", ", map { "$_ => $myhash{$_}" } keys %myhash) . " are the abcByLength sorted key => val pairs\n";
print "Done\n\n";
sub abcByLength {
my ($a, $b) = @_;
if(length($a) == length($b)) { return $a cmp $b; }
else { return length($a) <=> length($b) }
}
Run Code Online (Sandbox Code Playgroud)
Foo.pl使用一个名为MyIxHash的包,我创建了一个名为MyIxHash.pm的模块.该脚本按字母顺序排列:"SortByKey",我通过模块中的"IxHash"包继承.最后两种是给我带来问题的.当我创建的子:在数组上运行"SortKeyByFunc"时,它传入数组并将子例程作为参数传递.我试图采用这些论点并将它们与变量联系起来.
最后的排序应按字符串长度排序,然后按字母顺序排序.在foo.pl的底部提供了一个子程序,作为"abcByLength".与反向alpha排序相同,此子例程作为参数传递给我的SortKeyByFunc子例程.
对于这两种类型,似乎实际的排序工作是为我完成的,我只需要将这个子例程应用于我的数组.
我在这里的主要问题似乎是我不知道如果可能的话,如何采用我的子程序参数并通过它作为参数运行我的数组.我在我的阵列上运行我的方法不正确?
package MyIxHash;
#use strict;
use warnings;
use parent Tie::IxHash;
use Data::Dumper qw(Dumper);
sub SortKeyByFunc {
#my $class = shift;
my ($a, $b) = @_;
#this is a reference to the already alphabetaized array being passed in
my @letters = $_[0][1];
#this is a reference to the sub being passed in as a parameter
my $reverse = $_[1];
#this is my variable to contain my reverse sorted array
my @sorted = @letters->$reverse();
return @sorted;
}
1;
Run Code Online (Sandbox Code Playgroud)
"我的问题出现在我尝试的地方:
my @sorted = @letters->$reverse();我也尝试过:my @sorted = sort {$reverse} @letters;"
你真的很亲密; 正确的语法是:
my $reverse = sub { $b cmp $a };
# ...
my @sorted = sort $reverse @letters;
Run Code Online (Sandbox Code Playgroud)
还要注意,基于历史原因,sort将参数传递给(略)魔术全局变量中的比较函数,$a而$b不是@_,因此你不需要(实际上不应该)my ($a, $b) = @_;在你的sortsubs中做(除非)你用原型声明它们;参见perldoc -f sort for gritty details).
编辑:如果给你一个比较函数,由于某种原因确实期望它的参数@_,你不能改变该函数的定义,那么你最好的选择可能是将它包装在这样的闭包中:
my $fixed_sortsub = sub { $weird_sortsub->($a, $b) };
my @sorted = sort $fixed_sortsub @letters;
Run Code Online (Sandbox Code Playgroud)
或者干脆:
my @sorted = sort { $weird_sortsub->($a, $b) } @letters;
Run Code Online (Sandbox Code Playgroud)
编辑2:啊,我看到了/一个问题.当你写:
my @letters = $_[0][1];
Run Code Online (Sandbox Code Playgroud)
你最终得到的是一个包含任何东西的单元素数组$_[0][1],可能是一个数组引用.您应该立即取消引用它,如下所示:
my @letters = @{ $_[0][1] };
Run Code Online (Sandbox Code Playgroud)
或者只是保留现在作为参考,并在使用它时取消引用它:
my $letters = $_[0][1];
# ...
my @sorted = sort $whatever @$letters;
Run Code Online (Sandbox Code Playgroud)
编辑3: 一旦你设法对键进行排序,那么,正如duskwuff在他的原始答案中注意到的那样,你还需要Reorder()从你的父类调用方法,Tie :: IxHash来实际改变键的顺序.另外,第一行:
my ($a, $b) = @_;
Run Code Online (Sandbox Code Playgroud)
是什么应该是一个采用代码引用的对象方法完全不合适(事实上,如果你想稍后在相同的代码块中调用,实际上是词汇化$a并且$b是一个坏主意sort).应该读的是:
my ($self, $sortfunc) = @_;
Run Code Online (Sandbox Code Playgroud)
实际上,不是枚举原始代码似乎有问题的所有内容,而是修复它可能更容易:
package MyIxHash;
use strict;
use warnings;
use parent 'Tie::IxHash';
sub SortKeyByFunc {
my ($self, $sortfunc) = @_;
my @unsorted = $self->Keys();
my @sorted = sort { $sortfunc->($a, $b) } @unsorted;
$self->Reorder( @sorted );
}
1;
Run Code Online (Sandbox Code Playgroud)
或者干脆:
sub SortKeyByFunc {
my ($self, $sortfunc) = @_;
$self->Reorder( sort { $sortfunc->($a, $b) } $self->Keys() );
}
Run Code Online (Sandbox Code Playgroud)
(附注:我现在明白为什么比较函数被指定为采取他们的论点@_,而不是在全局$a和$b地方sort通常把他们:这是因为比较函数属于不同的包,$a并且$b是不足够神奇的是在同一每包公司,比如,$_和@_是.我想这可能会被周围的工作,但它会采取一些非常不平凡的挂羊头卖狗肉caller.)
(Pps.当你提交练习时,请相信我和duskwuff/Stack Overflow.祝学习Perl好运 - 相信我,这将是一项有用的技能.)