为什么我的Perl工作不合适?

时间:2013-01-20 05:49:12

标签: perl sorting inheritance methods 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) } 
}

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;

2 个答案:

答案 0 :(得分:5)

  

“我的问题发生在我尝试的位置:my @sorted = @letters->$reverse();我也尝试过:my @sorted = sort {$reverse} @letters;

你真的很亲密;正确的语法是:

my $reverse = sub { $b cmp $a };
# ...
my @sorted = sort $reverse @letters;

另请注意,基于历史原因,sort将参数传递给(略)魔术全局$a$b中的比较函数,而不是{{1}因此,您不需要(实际上不应该)在您的sortsubs中执行@_(除非您使用原型声明它们;有关详细信息,请参阅perldoc -f sort。)


编辑:如果您有一个比较函数,由于某种原因 期望<{1}}中的参数,并且您无法更改定义那个函数,那么你最好的选择可能是把它包装成这样的闭包:

my ($a, $b) = @_;

或简单地说:

@_

编辑2:啊,我看到了/一个问题。当你写:

my $fixed_sortsub = sub { $weird_sortsub->($a, $b) };

my @sorted = sort $fixed_sortsub @letters;

你最终得到的是一个包含my @sorted = sort { $weird_sortsub->($a, $b) } @letters; 的单元素数组,可能是array reference。您应该立即取消引用它,如下所示:

my @letters = $_[0][1];

或者只是保留现在作为参考,并在使用它时取消引用它:

$_[0][1]

编辑3 一旦你设法对密钥进行排序,那么,正如duskwuff在其原始答案中所说,你还需要从父类调用my @letters = @{ $_[0][1] }; 方法,Tie::IxHash实际更改键的顺序。另外,第一行:

my $letters = $_[0][1];
# ...
my @sorted = sort $whatever @$letters;

完全不合适于采用代码引用的对象方法(实际上,如果你想调用{{},Reorder()my ($a, $b) = @_; 是一个坏主意{1}}稍后在相同的代码块中)。应该阅读的内容如下:

$a

事实上,不是枚举原始代码似乎有问题的所有内容,而是修复它可能更容易:

$b

或简单地说:

sort

(Ps。我现在看到为什么比较函数被指定为在my ($self, $sortfunc) = @_; 中而不是在全局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; sub SortKeyByFunc { my ($self, $sortfunc) = @_; $self->Reorder( sort { $sortfunc->($a, $b) } $self->Keys() ); } 中使用@_通常放置它们的参数:这是因为比较函数属于不同的包,并且$a$b 不够神奇,在每个包中都是相同的,例如{{1} }和sort是。我想可以可以解决,但是$a需要一些非常重要的诡计。)

(Pps。当你提交练习时,请相信我和duskwuff / Stack Overflow。祝你学习Perl好运 - 相信我,这将是一项非常有用的技能。)

答案 1 :(得分:4)

您的SortKeyByFunc方法返回对数组进行排序的结果(@sorted),但它不会“就地”修改数组。因此,仅调用$t->SortKeyByFunc(...);并不会产生任何明显的永久性影响。

您需要在$t->Reorder()方法中调用SortKeyByFunc才能对阵列产生持久影响。我没有尝试过,但有点像:

$t->Reorder(@sorted);

在你的方法结束时可能就足够了。