Si può provare Arrays::Utils
, e lo fa sembrare bello e semplice, ma non sta facendo alcuna magia potente sul back-end. Ecco il codice array_diffs
:
sub array_diff(\@\@) {
my %e = map { $_ => undef } @{$_[1]};
return @{[ (grep { (exists $e{$_}) ? (delete $e{$_}) : (1) } @{ $_[0] }), keys %e ] };
}
Dal Arrays::Utils
non è un modulo standard, è necessario chiedersi se vale la pena lo sforzo di installare e mantenere questo modulo.Altrimenti, è abbastanza vicino alla risposta di DVK.
Ci sono alcune cose che devi fare attenzione e devi definire cosa vuoi fare in quel caso particolare. Diciamo:
@array1 = qw(1 1 2 2 3 3 4 4 5 5);
@array2 = qw(1 2 3 4 5);
Questi array sono gli stessi? O sono diversi? Hanno gli stessi valori, ma ci sono duplicati in @array1
e non @array2
.
Che dire di questo?
@array1 = qw(1 1 2 3 4 5);
@array2 = qw(1 1 2 3 4 5);
Direi che questi array sono gli stessi, ma Array::Utils::arrays_diff
permette di dissentire. Questo perché Array::Utils
presuppone che non vi siano voci duplicate.
E, anche le FAQ Perl evidenziate da mob affermano anche che Si presuppone che ogni elemento sia univoco in un determinato array. È una supposizione che puoi fare?
Non importa, gli hash sono la risposta. È facile e veloce cercare un hash. Il problema è cosa vuoi fare con valori unici.
Ecco una soluzione solida che si assume i duplicati non contano:
sub array_diff {
my @array1 = @{ shift() };
my @array2 = @{ shift() };
my %array1_hash;
my %array2_hash;
# Create a hash entry for each element in @array1
for my $element (@array1) {
$array1_hash{$element} = @array1;
}
# Same for @array2: This time, use map instead of a loop
map { $array_2{$_} = 1 } @array2;
for my $entry (@array2) {
if (not $array1_hash{$entry}) {
return 1; #Entry in @array2 but not @array1: Differ
}
}
if (keys %array_hash1 != keys %array_hash2) {
return 1; #Arrays differ
}
else {
return 0; #Arrays contain the same elements
}
}
Se duplicati sono importanti, avrete bisogno di un modo di contarli. Ecco come usare la mappa non solo per creare un hash digitato da ciascun elemento della matrice, ma anche contare i duplicati nella matrice:
my %array1_hash;
my %array2_hash;
map { $array1_hash{$_} += 1 } @array1;
map { $array2_hash{$_} += 2 } @array2;
Ora, si può passare attraverso ogni hash e verificare che non solo esistono le chiavi , ma che le loro voci corrispondono
for my $key (keys %array1_hash) {
if (not exists $array2_hash{$key}
or $array1_hash{$key} != $array2_hash{$key}) {
return 1; #Arrays differ
}
}
Si uscirà solo il ciclo for, se tutte le voci in %array1_hash
corrispondono alle loro voci corrispondenti in %array2_hash
. Ora, devi mostrare che tutte le voci in %array2_hash
corrispondono anche alle loro voci in %array1_hash
e che %array2_hash
non ha più voci. Fortunatamente, possiamo fare quello che abbiamo fatto prima:
if (keys %array2_hash != keys %array1_hash) {
return 1; #Arrays have a different number of keys: Don't match
}
else {
return; #Arrays have the same keys: They do match
}
Forse si potrebbe inviare il codice vero e proprio nidificato ciclo che si' siamo arrivati così lontano, questo ci aiuterà a trovare un modo migliore (se ce n'è uno). –
Se fossi in te, inizierei con CPAN. Dai un'occhiata a 'List :: Compare' - e in particolare, la sezione in basso" If You Like List :: Compare, you'll love ... "Sembra che tu possa voler cercare qualcosa implementato in C piuttosto che puro Perl. http://search.cpan.org/perldoc/List::Compare – Telemachus
Vuoi dire che devi sapere se un array è un sottoinsieme dell'altro? O se sono esattamente uguali? O se hanno gli stessi elementi, ma in un ordine diverso? E hai bisogno di sapere quali elementi mancano o semplicemente che non sono la stessa cosa? – Schwern