Quelle est la meilleure façon de mettre en œuvre l'opérateur APL compressif en Perl?

StackOverflow https://stackoverflow.com/questions/6823505

  •  26-10-2019
  •  | 
  •  

Question

Parfois, ma familiarité APL me donne des idées algorithmiques pour la résolution des problèmes que je réimplémenter dans une langue que j'ai -. Perl, par exemple

Je l'ai traité un fichier texte pour créer un vecteur booléen indiquant les champs utilisés dans un fichier délimité, et maintenant je veux sortir les indices de ces champs utilisés, et les noms des champs utilisés. Dans l'APL, j'utiliser l'opérateur sur le vecteur compress des noms de champs, et sur le iota du nombre de champs.

En Perl, je l'ai fait:

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

et

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

@UsedFields est un tableau contenant 0 à 1 et utilisé pour les champs utilisés.

  1. Je ne suis pas vraiment en utilisant la carte avec ?:() pour compresser Simuler - est-il une meilleure façon (mon programme réel, il fait une troisième fois lors de la simulation d'une verticale ou une réduction sur le fichier)

  2. Je ne aime pas vraiment faire la carte sur les index pour obtenir les résultats - est-il une meilleure façon de calculer cela? (Je suppose que l'une optimisation serait de calculer les index utilisés, puis

    @UsedFieldNames = @FieldNames[@UsedIndexes];

Était-ce utile?

La solution

Autres façons:

my @UsedFieldNames = map { ( $FieldNames[$_] ) x !!$UsedFields[$_] } 0..$#UsedFields;
my @UsedFieldNames = @FieldNames[ grep $UsedFields[$_], 0..$#UsedFields ];

Autres conseils

L'approche avec grep ou d'une carte est la bonne, et est ce que l'APL aurait été en utilisant les coulisses. Vous pouvez cacher en Perl aussi avec un sous-programme:

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

Si vous travaillez avec des références de tableau, vous avez quelques autres options syntaxiques, et dans ce cas je pourrais l'écrire comme méthode scalaire pour l'application de infix:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top