Quelle est la meilleure façon de copier un hachage de hash en Perl? [dupliquer]

possibilité de duplication:

Quelle est la meilleure façon de faire une copie profonde d'une structure de données en Perl?

avant que je commence à coder moi-même et à réinventer la roue, comment copier un hachage de hachages sans dupliquer les hachoirs?

je lis un hash de hash de hash via Config::General . c'est à dire, la structure des données est la suivante:

my %config = ( group => { item1 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item2 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item3 => { foo => 'value',
                                     bar => 'value',
                                   },
                        },
             );

je retire alors mon groupe de la config en le déréférencant et en changeant le contenu à l'exécution avant de réécrire le fichier de configuration:

my %group = %{$config{'group'}};

le problème est que je dois vérifier pour voir si des changements ont été faits et d'apporter des changements associés à la structure du système de fichiers. Je ne peux pas le faire en cochant:

if ($group{'item1'}{'foo'} ne $config{'group'}{'item1'}{'foo'}) {
    ### Stuff!
}

comme $group{'item1'} et $config{'group'}{'item1'} sont tous les deux les mêmes hashref.

maintenant alors qu'il devrait être trivial de simplement re-analyser le fichier de configuration, et comparer la copie parsée à partir du disque par rapport à la version éditée juste avant de sauvegarder sur le disque, je suis sûr qu'il y a un moyen d'obtenir une déréférence imbriquée d'une structure de données complexe, en copiant le contenu des références hachées et pas simplement en copiant les références elles-mêmes. Un examen superficiel de la CPAN ne révèle rien. Ce qui me manque?

de Référence

Eu ma réponse:

#!/usr/bin/perl

use Benchmark qw(:all) ;
use Storable qw(dclone);
use Clone qw(clone);

my %config = ( group => { item1 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item2 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item3 => { foo => 'value',
                                     bar => 'value',
                                   },
                        },
             );

my $ref = $config{'group'};

timethese(100000, {
  'Clone' => sub { my %group = %{ clone $ref }},
  'Storable' => sub {  my %group = %{ dclone $ref }},
});

résultats dans:

Benchmark: timing 100000 iterations of Clone, Storable...
   Clone:  2 wallclock secs ( 2.26 usr +  0.01 sys =  2.27 CPU) @ 44052.86/s (n=100000)
Storable:  5 wallclock secs ( 4.71 usr +  0.02 sys =  4.73 CPU) @ 21141.65/s (n=100000)
22
demandé sur Community 2009-10-10 02:14:13

4 réponses

use Storable qw(dclone);
$group2 = dclone(\%group);
35
répondu codehead 2009-10-09 22:18:29

De la Stockables::dclone de la documentation, j'ai trouvé Clone :

my $copy = clone (\@array);

# or

my %copy = %{ clone (\%hash) };

N'ont pas besoin de flexibilité, et prétend être plus rapide que stockable::dclone .

29
répondu Oesor 2009-10-10 00:32:11

Profondeur structure de données 101:

  • Utiliser Stockables 's dclone de faire une copie d'une structure, et freeze et thaw pour sérialiser/désérialiser pour le stockage (disons dans une base de données, ou un cookie http (mais vous devez chiffrer tout ce que vous envoyez à l'utilisateur afin de le rendre plus difficile à falsifier).
  • utiliser données::comparer (ou Test:: Deep ou Test:: Differences à l'intérieur d'un test unitaire) pour comparer deux structures de données profondes.
  • Utiliser Data::Dumper ou Données::Dump débogage pour voir ce que vos objets. Mais ne l'utilisez pas comme une licence pour altérer les internes d'un autre objet; utilisez L'API. :)
7
répondu Ether 2009-10-09 22:42:49

peut toujours stocker le hash via stockable ou Data::Dumper, et réattribuer la valeur stockée dans un nouveau hash. Ceci devrait obtenir une copie complète sans maintenir les liens référencés.

use Storable;
my $serialized = freeze \%config;
my %newconfig = %{ thaw($serialized) };
-3
répondu zigdon 2009-10-09 22:19:01