2

APL に慣れていると、問題解決のためのアルゴリズムのアイデアが得られることがあります。それを、自分が持っている言語 (たとえば Perl) で再実装します。

そのため、テキスト ファイルを処理して、区切りファイルで使用されているフィールドを示すブール ベクトルを作成しました。これらの使用されているフィールドのインデックスと、使用されているフィールドの名前を出力したいと考えています。APL では、フィールド名のベクトルとフィールド数のイオタに対して圧縮演算子を使用します。

Perl では、次のようにしました。

my @UsedFieldNames = map { $UsedFields[$_] ? $FieldNames[$_] : () } 0 .. $#UsedFields;

say join " ", map { $UsedFields[$_] ? $) : () } 0 .. $#UsedFields;

ここ@UsedFieldsで、未使用のフィールドは 0、使用済みのフィールドは 1 の配列です。

  1. ?:()圧縮をシミュレートするためにmap with を使用するのはあまり好きではありません- もっと良い方法はありますか?

  2. 結果を得るためにインデックスをマップするのは本当に好きではありません - それを計算するためのより良い方法はありますか? (最適化の 1 つは、使用されているインデックスを最初に計算してから、

    @UsedFieldNames = @FieldNames[@UsedIndexes];

4

2 に答える 2

4

grep または map を使用したアプローチは正しいものであり、APL が舞台裏で使用していたものです。サブルーチンを使用して、Perl でもそれを隠すことができます。

sub compress (\@\@) {
    @{$_[0]}[ grep $_[1][$_] => 0 .. $#{$_[1]} ]
#or use:
#   map {$_[1][$_] ? $_[0][$_] : ()} 0 .. $#{$_[0]}
}

my @source = qw(one two three four);
my @ok     = qw(0   1   0     1   );

my @new = compress @source, @ok;

say "@new"; # two four

配列参照を使用している場合は、他にもいくつかの構文オプションがあります。この場合、中置適用のスカラー メソッドとして記述できます。

my $compress = sub {
    my $src = shift;
    my $ok  = @_ == 1 && ref $_[0] eq 'ARRAY' ? shift : \@_;
    wantarray ?            @$src[ grep $$ok[$_] => 0 .. $#$ok ]
              : sub{\@_}->(@$src[ grep $$ok[$_] => 0 .. $#$ok ])
};

my $source = [qw(one two three four)];
my $ok     = [qw(1   0   1     0   )];

my $new = $source->$compress($ok);

say "@$new"; # one three
say join ' ' => $source->$compress(0, 1, 1, 0); # two three
于 2011-07-26T00:05:12.967 に答える
3

他の方法:

my @UsedFieldNames = map { ( $FieldNames[$_] ) x !!$UsedFields[$_] } 0..$#UsedFields;
my @UsedFieldNames = @FieldNames[ grep $UsedFields[$_], 0..$#UsedFields ];
于 2011-07-25T23:21:34.367 に答える