3

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.pm という名前のモジュールを作成した MyIxHash という名前のパッケージを使用します。このスクリプトは、モジュールの「IxHash」パッケージを介して継承した「SortByKey」というアルファベット順の並べ替えを実行します。最後の 2 つの種類は、私に問題を与えるものです。私が作成したサブ「SortKeyByFunc」が配列で実行されると、配列とサブルーチンが引数として渡されます。これらの引数を取り、それらを変数に関連付けようとしました。

最後の並べ替えは、文字列の長さで並べ替え、次にアルファベット順に並べ替えることになっています。このためのサブルーチンは、foo.pl の下部に「abcByLength」として提供されます。リバース アルファ ソートと同様に、このサブルーチンはパラメーターとして 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;
4

2 に答える 2

5

「私が試したところに問題が発生しました:my @sorted = @letters->$reverse();私も試しました: my @sorted = sort {$reverse} @letters;

あなたは本当に親しかった。正しい構文は次のとおりです。

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

また、基本的に歴史的な理由から、ではなく(わずかに) マジック グローバルとでsort比較関数に引数を渡すことに注意してください。プロトタイプでそれらを宣言します;細かい詳細についてはperldoc -f sortを参照してください)。$a$b@_my ($a, $b) = @_;


編集:何らかの理由でその引数にあることを期待する比較関数が与えられ、@_その関数の定義を変更できない場合、最善の策はおそらく次のようなクロージャーでラップすることです:

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

my @sorted = sort $fixed_sortsub @letters;

または単に:

my @sorted = sort { $weird_sortsub->($a, $b) } @letters;

編集 2:ああ、問題が発生しました。あなたが書くとき:

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

$_[0][1]最終的に a になるのは、おそらく配列参照であるものを含む単一要素の配列です。次のように、すぐに逆参照する必要があります。

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

または、今のところ参照として保持し、使用するときに逆参照します。

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

編集 3: キーを並べ替えることができたら、duskwuff が元の回答で指摘しているようにReorder()、親クラスのTie::IxHashからメソッドを呼び出して、実際にキーの順序を変更する必要もあります。また、最初の行:

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

は、コード参照を受け取るオブジェクト メソッドであると想定されているものでは完全に場違いです (実際、レキシカライズ$aを行っており、後で同じコード ブロックで$b呼び出したい場合はとにかく悪い考えです)。sort読むべきものは次のようなものです:

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どこsortに置くかがわかりました。これは、比較関数が別のパッケージに属しており、同じであるほど魔法的$a$bないためです。すべてのパッケージは、たとえば、$_およびあります。これは回避できる@_と思いますが、かなり複雑なトリックが必要になるでしょう。)caller

(Pps. 練習問題を提出する際は、私と Duskwuff / Stack Overflow の功績を認めてください。そして、Perl の学習を頑張ってください — 信じてください。これは役に立つスキルになるでしょう。)

于 2013-01-20T07:06:26.923 に答える
4

SortKeyByFuncこのメソッドは、配列を並べ替えた結果 ( ) を返しますが@sorted、配列を「その場で」変更しません。その結果、呼び出しただけで$t->SortKeyByFunc(...);は目に見える永続的な効果はありません。

配列に永続的な影響を与えるには$t->Reorder()、メソッド内で呼び出す必要があります。SortKeyByFunc私はそれを試していませんが、次のようなものです:

$t->Reorder(@sorted);

メソッドの最後で十分な場合があります。

于 2013-01-20T06:05:28.690 に答える