2013-03-08 4 views
8

Est-ce que quelqu'un sait comment faire un hachage avec des paires de chaînes servant de clés en Perl?Paires en tant que clés de hachage

Quelque chose comme ...

{ 
    ($key1, $key2) => $value1; 
    ($key1, $key3) => $value2; 
    ($key2, $key3) => $value3; 

etc ....

+0

connexes: [Hash :: multitouche] (http://p3rl.org/Hash::MultiKey) [Tie :: RefHash] (http://p3rl.org/Tie::RefHash) [Perl peut-il stocker une référence de tableau en tant que clé de hachage?] (Http: // stackoverflow.com/questions/3083433/can-perl-store-an-array-reference-as-a-hash-key) [Comment utiliser une 'référence de sous-programme' comme clé de hachage] (http://stackoverflow.com/questions/10795386/how-to-use-a-subroutine-reference-as-a-hash-key) – daxim

Répondre

12

Vous ne pouvez pas avoir une paire de scalaires comme une clé de hachage, mais vous pouvez faire un multi-niveaux hachage:

my %hash; 
$hash{$key1}{$key2} = $value1; 
$hash{$key1}{$key3} = $value2; 
$hash{$key2}{$key3} = $value3; 

Si vous voulez définir à la fois:

my %hash = ($key1 => { $key2 => $value1, $key3 => $value2 }, 
      $key2 => { $key3 => $value3 }); 

Alternativement, si cela fonctionne pour votre situation, vous pourriez juste concaténer votre clé s ensemble

$hash{$key1 . $key2} = $value1; # etc 

Ou ajouter un séparateur pour séparer les clés:

$hash{"$key1:$key2"} = $value1; # etc 
+4

votre première suggestion est grande, comme pour la seconde, il est préférable d'avoir un séparateur pour éviter les collisions comme 123 456 et 12 3456 ... – Lucas

+3

Il y a des caractères ASCII définis à cet effet; le Séparateur d'Unité (hex 1f) est probablement le plus approprié. – chepner

+0

Virgule, pas non. – tchrist

1

Je fais ceci:

{ "$key1\x1F$key2" => $value, ... } 

Habituellement avec une méthode d'assistance:

sub getKey() { 
    return join("\x1F", @_); 
} 

{ getKey($key1, $key2) => $value, ... } 

--- - EDIT -----

Mis à jour le code ci-dessus pour utiliser le séparateur d'unité ASCII par l'recommendation from @chepner above

+0

Ou vous pouvez définir $; à "\ x1F" et utiliser $ hash {$ key1, $ key2} = $ valeur ou {"$ key1 $; $ key2" => $ valeur} – MkV

+0

@MkV, dois aimer perl ... soooooo beaucoup de façons de tout faire :) – Lucas

1

Utilisation: Multiple clés d'une valeur unique dans un hachage peuvent être utilisés pour la mise en œuvre d'un 2D matrice ou Matrice N-dimensionnelle!

#!/usr/bin/perl -w 
use warnings; 
use strict; 
use Data::Dumper; 

my %hash =(); 

my ($a, $b, $c) = (2,3,4); 
$hash{"$a, $b ,$c"} = 1; 
$hash{"$b, $c ,$a"} = 1; 

foreach(keys(%hash)) 
{ 
    my @a = split(/,/, $_); 
    print Dumper(@a); 
} 
2

Vous pouvez utiliser un invisible separator pour rejoindre les coordonnées:

Principalement pour les mathématiques, le séparateur invisible (U+2063) fournit un séparateur entre les caractères où la ponctuation ou l'espace peut être omis, comme dans deux -dimensional index comme i⁣j.

#!/usr/bin/env perl 

use utf8; 
use v5.12; 
use strict; 
use warnings; 
use warnings qw(FATAL utf8); 
use open qw(:std :utf8); 
use charnames qw(:full :short); 

use YAML; 

my %sparse_matrix = (
    mk_key(34,56) => -1, 
    mk_key(1200,11) => 1, 
); 

print Dump \%sparse_matrix; 

sub mk_key { join("\N{INVISIBLE SEPARATOR}", @_) } 

sub mk_vec { map [split "\N{INVISIBLE SEPARATOR}"], @_ } 
~/tmp> perl mm.pl |xxd 
0000000: 2d2d 2d0a 3132 3030 e281 a331 313a 2031 ---.1200...11: 1 
0000010: 0a33 34e2 81a3 3536 3a20 2d31 0a   .34...56: -1.
0

Utilisez $; implicitement (ou explicitement) dans vos clés de hachage, utilisées pour l'émulation multidimensionnelle, comme ceci:

my %hash; 
$hash{$key1, $key2} = $value; # or %hash = ($key1.$;.$key2 => $value); 
print $hash{$key1, $key2} # returns $value 

Vous pouvez même $; à \ x1F si nécessaire (la valeur par défaut est \ 034, de SUBSEP awk):

local $; = "\x1F"; 
Questions connexes