Insérer tableau dans tableau associatif [Fermé]

Signaler
Messages postés
23763
Date d'inscription
dimanche 26 août 2001
Statut
Modérateur
Dernière intervention
13 janvier 2020
-
Messages postés
23763
Date d'inscription
dimanche 26 août 2001
Statut
Modérateur
Dernière intervention
13 janvier 2020
-
Bonjour,

je cherche à insérer un tableau (normal) dans une cellule d'un tableau associatif afin de pouvoir le parcourir plus tard.

Genre :

'boucle sur $i
$TAB{$i}{0} = "toto";
$TAB{$i}{1} = "1";
'boucle de remplissage de tableau
@TABLEAU[$j][0] = "titi"
@TABLEAU[$j][1] = "tata"
'fin boucle remplissage
$TAB{$i}{2} = @TABLEAU
fin boucle $i
....
'boucle sur $i
@TABLEAU = $TAB{$i}{2}
'boucle sur @TABLEAU
...
'fin boucle
'fin boucle

Mon problème est que scalar(@TABLEAU) est égal à 1 quand je veux le récupérér, donc j'ai un peu perdu des infos dans la manip...

Je dois faire une énorme bourde, mais je ne m'y connais pas assez en structures de données pour voir où...

Si quelqu'un peut m'éclairer, merci d'avance !

A+ blux
 "Les cons, ça ose tout.
C'est même à ça qu'on les reconnait"

2 réponses

Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020
914
Salut blux,

Il y a plusieurs problèmes.

Tu n'affectes pas correctement les valeurs du tableau.

C'est comme cela que l'on fait :

# déclaration
my @TABLEAU;

# affectation
$TABLEAU[0][0] = "titi";


Ensuite, pour intégrer ton tableau à ton hash, tu dois pouvoir faire :
$TAB{$i}{2} = \@TABLEAU;
si ce que tu veux c'est affecter une référence au tableau créé

La référence fonctionnera comme un "pointeur" dans d'autres langages : tu accèdes à la même structure de données en dé-référençant la référence.

Note que le nommage de "%TAB" pour un hash n'est pas forcément un choix très lisible.

Le code suivant illustre un exemple de mise en oeuvre :
#!/usr/bin/perl

use strict;
use warnings;

my %hash;
$hash{0}{0} = "toto";
$hash{0}{1} = "1";

my @arr;
$arr[0][0] = "titi";
$arr[0][1] = "tata";

# on assigne une référence au tableau
$hash{0}{2} = \@arr;

print "Affichage du contenu du tableau référencé :\n";
# afficher "titi"
print $hash{0}{2}[0][0] . "\n";
# afficher "tata"
print $hash{0}{2}[0][1] . "\n";

# modification d'un élément du tableau
print "modification d'un élément du tableau\n";
$arr[0][0] = "tutu";

print "Affichage après modification\n";
# l'affichage en passant par la référence affiche tutu
print $hash{0}{2}[0][0] . "\n";
# afficher "tata"
print $hash{0}{2}[0][1] . "\n";


cela donne :

Affichage du contenu du tableau référencé :
titi
tata
modification d'un élément du tableau
Affichage après modification
tutu
tata

mais cela a l'air très compliqué ta structure de données.


Dal
Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020
914
Je ne suis pas sûr de bien comprendre.

Mais si ce que tu demandes c'est : est-ce que je peux me servir de la référence stockée dans le hash d'une autre façon qu'à partir du hash, la réponse est oui.

Tu peux le faire à partir du tableau d'origine, comme montré par le code d'exemple, ou tu peux copier cette référence dans une autre variable et déréfécencer à partir de là.

Tu peux aussi créer directement un tableau dans ton hash, sans avoir à créer un tableau préexistant, y pousser les valeurs avec push, et récupérer une référence à ce tableau pour gérer ce contenu indépendamment du hash.


Dal
Messages postés
23763
Date d'inscription
dimanche 26 août 2001
Statut
Modérateur
Dernière intervention
13 janvier 2020
2 962
Je ne me suis pas fait suffisamment comprendre, je pense.
Ce que je veux, c'est mettre un tableau différent pour chaque 'ligne' de mon tableau hashé.

Lorsque je vais relire mon tableau hashé, je veux récupérer le tableau qui est rattaché à chaque 'ligne'. C'est plus clair ?

exemple :

un tableau de hash pour un matériel informatique avec toute une série d'infos uniques (type, date d'achat, ram, dd...) ET pour chaque matériel la liste de ses pannes, par exemple. Donc tableau des pannes inséré dans la cellule qui va bien du tableau de hash.

Quand je relis mon tableau de hash, je récupère mes infos 'matériel' et je veux aussi boucler sur toutes les pannes de chaque matériel.

Pour le reste de tes explications, je veux bien un 'tit exemple, si c'est pas abuser...

Tu peux le faire à partir du tableau d'origine, comme montré par le code d'exemple, ou tu peux copier cette référence dans une autre variable et déréfécencer à partir de là.

Tu peux aussi créer directement un tableau dans ton hash, sans avoir à créer un tableau préexistant, y pousser les valeurs avec push, et récupérer une référence à ce tableau pour gérer ce contenu indépendamment du hash.


Et comment puis-je faire pour parcourir le tableau que j'ai référencé ? Comment obtenir sa taille (fonction scalar ?)

print $hash{0}{2}[0][0] . "\n";


<edit>
bon, j'ai fini par trouver la bonne syntaxe !

Mais comme j'ai omis de dire que $arr est réinitialisé pour chaque ligne de $hash (je veux un tableau avec des valeurs différentes) seule la dernière 'version' de mon $arr est stockée dans toutes les lignes de $hash.

Je veux créer un tableau $arr différent pour chaque ligne de $hash et récupérer le $arr qui correspond à ce que j'ai mis lors du remplissage à mon parcours final de $hash

Et là, ça coince...
Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020
914
ok, et tu stockes ta liste de matériels dans un array pour pouvoir énumérer le parc informatique?
Messages postés
23763
Date d'inscription
dimanche 26 août 2001
Statut
Modérateur
Dernière intervention
13 janvier 2020
2 962
C'est exactement ça, sauf que ce n'est pas du tout pour gérer un parc informatique ;-)

C'est juste, comme je l'expliquais, pour simuler une relation 1-n de bases de données, si le concept t'est familier...
Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020
914
ok, vois mon code dans ce message.

j'ai finalement utilisé un hash pour tout stocker, en considérant qu'il doit être possible d'identifier chaque matériel du parc par un numéro de série unique.
Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020
914
Salut blux,

Avec tes indications plus concrètes de structure de données de matériels d'un parc informatique avec leurs pannes respectives, je comprends mieux qu'avec des toto et des titi :-)

essayes un truc comme cela :

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

# for storing all the park
my %park;

# for adding a new hardware
sub add_hardw {
    my ($serial_num, $name, $type, $date_bought, $ram, $hd) = @_;
    my @failures;

    # adding an entry to the hash using the serial number as the key, cloning the values
    $park{$serial_num} = {
        name => $name,
        type => $type,
        date_bought => $date_bought,
        ram => $ram,
        hd => $hd,
        failures => \@failures
    };
}

print "Création d'une nouvelle entrée pour un matériel\n";
add_hardw("123456", "PC12", "desktop", "2014-02-26", "4GB", "500GB");

print "ajout de quelques pannes\n";
push $park{"123456"}{failures}, "2015-01-05 - panne du ventilateur";
push $park{"123456"}{failures}, "2015-01-06 - câble ethernet sectionné";

print "affectation d'une référence de la liste des pannes d'un matériel à un scalaire \$temp\n";
my $temp = $park{"123456"}{failures};

print "changement du libellé de la première panne en passant par %park\n";
$park{"123456"}{failures}[0] = "2015-01-05 - panne du ventilateur (coincé par un stylo)";

print "changement du libellé de la seconde panne en passant par \$temp\n";
@$temp[1] = "2015-01-06 - câble ethernet sectionné (dévoré par un rongeur)";

print "Création d'une nouvelle entrée pour un autre matériel, avec ajout d'une panne\n";
add_hardw("123457", "Imprimante YH", "imprimante", "2014-05-02", "1GB", "150GB");
$temp = $park{"123457"}{failures};
push @$temp, "2015-01-06 - l'imprimante ne s'allume plus";
                                                                                                                                                                                                                   
print Dumper(%park);

En ligne 16, les accolades à la suite du signe égal dans la création de la nouvelle entrée de hash opèrent une copie des données contenues dans les variables utilisées (locales à la fonction dans ce code) qui sont mises dans le hash (qui est une variable globale, utilisable ailleurs dans le code).

Parmi les éléments clonés, en ligne 22,
failures => \@failures
clone une référence à un tableau.

Lorsqu'une autre entrée de hash est créée en ligne 43, c'est un nouveau hash qui est ajouté, avec des données indépendantes.

On crée donc un hash de hashs, chaque hash contenu incluant une référence à un tableau (pour stocker les anomalies séquentiellement).

Le code illustre comment tu peux accéder au tableau en passant par le hash, ou par une référence au tableau stocké dans une des entrées du hash, et comment déréférencer une référence d'un tableau stockée dans un scalaire ($temp est la référence et @$temp la déréférence comme un tableau).

Cela dit, je trouve personnellement la notation
$park{"123456"}{failures}[0]
suffisamment lisible, et je ne vois pas vraiment l'intérêt de passer par une variable temporaire pour la manipulation indirecte du tableau.

J'ai aussi pris le parti de ce que %park soit un hash dans cet exemple, dont la clef est un numéro unique identifiant le matériel.


Dal
Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020
914
désolé, je n'ai pas eu une minute aujourd'hui.

je vais regarder cela, mais le message dit simplement que $TAB_GRP{$GRP}{TAILLE} n'est pas un tableau, ce qui est normal, car c'est effectivement une référence à un tableau (soit un scalaire), et non un tableau.

sans avoir testé, il devrait suffire de faire :
push @{$TAB_GRP{$GRP}{TAILLE}},[$ANC_CLI ,$TOT_CLI];
.

pour la déréférencer et convaincre push que c'est bien un array auquel il accède

cela dit, je n'ai pas testé :-)


Dal
Messages postés
23763
Date d'inscription
dimanche 26 août 2001
Statut
Modérateur
Dernière intervention
13 janvier 2020
2 962
désolé, je n'ai pas eu une minute aujourd'hui.
Ca arrive à tout le monde ;-)

Je teste dès demain...

Et comment pourrais-je lister TAILLE dans l'ordre de $TOT_CLI pour chaque $TAB_GRP ?

<edit>
Ca marche bien, ne reste plus qu'à trier comme je le souhaite...
Messages postés
23763
Date d'inscription
dimanche 26 août 2001
Statut
Modérateur
Dernière intervention
13 janvier 2020
2 962
Pour trier, j'ai fait un tableau intermédiaire que je parcours et que j'affiche ensuite (deux boucles, donc...).
Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020
914
bravo !

comme le hash de base contient une arborescence d'éléments hétérogènes, si ce que tu veux trier ne se situe pas au même niveau, cela a du sens d'extraire préalablement ce que tu veux trier, pour le mettre dans une structure homogène plus facile à trier.

par contre, si tu tries au même niveau, par exemple, tu tries un tableau donné stocké (en réalité accessible) dans (à partir de) la structure du hash, ce n'est en revanche pas nécessaire.

sort est très puissant, tu peux définir tes propres fonctions de comparaison : https://perldoc.perl.org/functions/sort.html


Dal
Messages postés
23763
Date d'inscription
dimanche 26 août 2001
Statut
Modérateur
Dernière intervention
13 janvier 2020
2 962 >
Messages postés
5446
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
27 novembre 2020

en fait, c'est ce que je voulais faire depuis le début : insérer un tableau trié dans une cellule pour pouvoir le récupérer à la fin...

j'ai déjà pratiqué le sort 'customisé' ;-)