Qual è il modo migliore per attuare l'APL operatore di comprimere in Perl?
Domanda
A volte la mia APL familiarità mi dà idee algoritmiche per la soluzione dei problemi che ho re-implementare in una lingua che ho -. Perl, ad esempio
Così ho elaborato un file di testo per creare un vettore booleano che indica i campi utilizzati in un file delimitato, e ora voglio uscita gli indici di quei campi utilizzati, ei nomi dei campi utilizzati. In APL, vorrei utilizzare l'operatore comprimere il vettore di nomi dei campi, e sopra la virgola del numero di campi.
In Perl, ho fatto questo:
my @UsedFieldNames = map { $UsedFields[$_] ? $FieldNames[$_] : () } 0 .. $#UsedFields;
e
say join " ", map { $UsedFields[$_] ? $) : () } 0 .. $#UsedFields;
dove @UsedFields
è un array contenente 0 per inutilizzato e 1 per campi usati.
-
mi piace in realtà non usando la mappa con
/ li>?:()
per comprimere simulare - c'è un modo migliore (il mio vero programma lo fa per la terza volta in cui la simulazione di una verticale o una riduzione sul file) -
Io non piace molto fare la mappa sopra gli indici per ottenere i risultati - c'è un modo migliore per calcolare questo? (Credo che un'ottimizzazione sarebbe quello di calcolare gli indici utilizzati, poi
@UsedFieldNames = @FieldNames[@UsedIndexes];
Soluzione
Altri modi:
my @UsedFieldNames = map { ( $FieldNames[$_] ) x !!$UsedFields[$_] } 0..$#UsedFields;
my @UsedFieldNames = @FieldNames[ grep $UsedFields[$_], 0..$#UsedFields ];
Altri suggerimenti
L'approccio con grep o una mappa è quella giusta, ed è ciò che APL sarebbe stato utilizzando dietro le quinte. È possibile nascondere che in Perl anche con una subroutine:
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
Se si lavora con riferimenti ad array, avete alcune altre opzioni sintattiche, e in questo caso mi potrebbe scrivere come metodo scalare per l'applicazione infisso:
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