2016-02-23 1 views
0

У меня есть массивы хеш-ссылок в Perl. Мне нужно сравнить их, т. Е. Эффективно делать то, что делает array_minus(), но мне нужно сделать сравнение с контентом хеша, а не ссылкой.Альтернатива array_minus, которая расширяет ссылки в Perl

Возьмите этот MWE:

#!/usr/bin/perl 
use Array::Utils qw(:all); 
use Data::Dumper; 

my %en = ('first' => 'one', 'second' => 'two', 'third' => 'three'); 
my %en2 = ('first' => 'one', 'second' => 'two', 'third' => 'three'); 
my %eo = ('first' => 'unu', 'second' => 'du', 'third' => 'tri'); 

my @set = (\%en, \%eo); 
my @subset = (\%en2); 

print(Dumper(array_minus(@set,@subset))); 

Я считаю, что array_minus() сравнивает ссылки, которые отличаются, так что выход:

$VAR1 = { 
      'first' => 'one', 
      'second' => 'two', 
      'third' => 'three' 
     }; 
$VAR2 = { 
      'first' => 'unu', 
      'second' => 'du', 
      'third' => 'tri' 
     }; 

Есть ли альтернатива, или вариант, который бы сравнение по содержанию хешей? Конечно, когда хеши в MWE не включены в качестве ссылки, сравнение работает правильно, и возвращается только один хеш.

+0

Не можете просто перебрать и сравнить себя? – fugu

+0

Конечно, я могу сделать это сам, но функции библиотеки всегда лучше оптимизированы и написаны людьми, которые додумались до конца. Так что пока есть один, это лучший способ пойти. – Frigo

ответ

2

Что-то, как это должно работать (непроверенные):

sub serialize { 
    use JSON::XS; 
    JSON::XS->new->pretty(0)->ascii(1)->canonical(1)->encode($_[0]) 
} 

sub array_minus_deep(\@\@) { 
    my ($array,$minus) = @_; 

    my %minus = map((serialize($_) => 1), @$minus); 
    grep !$minus{ serialize($_) }, @$array 
} 
+0

Действительно, он работает! Мне просто пришлось заменить 'terse'' relaxed' и инвертировать логику: 'JSON :: XS-> new-> relaxed (0) -> ascii (1) -> canonical (1) -> encode ($ _ [ 0]); ' – Frigo

 Смежные вопросы

  • Нет связанных вопросов^_^