Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    doctorant
    Inscrit en
    février 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Alpes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : doctorant

    Informations forums :
    Inscription : février 2018
    Messages : 4
    Points : 1
    Points
    1

    Par défaut Concaténer des tableaux de hachage

    Bonjour à tous,

    je débute sur perl (d'habitude j'utilise bash) et je bloque en essayant de concaténer des tableaux de hachage. Le but de la manip est de concaténer plusieurs fichiers contenant des séquences, du style :

    fichier 1 :
    ind1 [sequence]
    ind2 [sequence]
    ind5 [sequence]

    fichier 2 :
    ind3 [sequence]
    ind4 [sequence]
    ind5 [sequence]

    sachant que tous les individus ne sont pas représentés dans tous les fichiers (il va donc falloir que j'ajoute les données manquantes au fil de la concaténation).

    ce que j'ai fais pour l'instant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open(ind, '<', 'concat');
    my %concat=<ind>;
    print %concat;
    créé un tableau de hashage dont les clés sont les noms de mes individus (contenus dans le fichier concat).

    ensuite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open(locus1, '<', 'locus0001');
    my %locus1=<locus1>;
    while(<locus1>){/([A-Za-z0-9]*)[[:space:]]*(.*)/; push @{$concat{$1}}, $2, "\n";}
    J'ouvre mon premier fichier de séquences (locus0001), je le stocke dans un tableau de hashage et je le concatène avec celui contenant les noms d'individus.
    Seulement, ca ne marche pas et j'obtiens quelque chose comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    Neu83ARRAY(0x13b8130)Sbz179 
    And54 
    oph_D 
    Brk117 
    BZ1 
    Brk120 
    1488ARRAY(0x13b7fc8)Neu73 
    Shv51 
    Dej22 
    Neu56 
    Ker382 
    Sbz177 
    Krk148 
    Neu50 
    Neu18 
    BZ16 
    Sis367 
    SGH90 
    Ap106 
    MrD264 
    Neu83 
    Ker380 
    And57 
    SGH88 
    Tov320 
    smk228 
    Sis354 
    Voj344 
    Smk226 
    Ngs408 
    1488 
    DgH208 
    Krk150 
    ToV319 
    DgH207 
    Neu04 
    MrD266 
    Neu55 
    Neu11 
    Neu84ARRAY(0x13cf428)Neu84 
    Neu36 
    Neu73ARRAY(0x13b80a0)Ap105 
    Neu72 
    Shv43 
    oph_T 
    Ngs394 
    Voj345
    En lieu et place de mes séquences, une chaine de type ARRAY(...), et je ne sais pas ce que ca veut dire, et il y a des doublons dans les noms des individus...

    Quelqu'un aurait une idée ?

    merci d'avance,
    Lois.

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    mai 2012
    Messages
    3 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : mai 2012
    Messages : 3 542
    Points : 12 192
    Points
    12 192
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par lois_rancilhac Voir le message

    fichier 1 :
    ind1 [sequence]
    ind2 [sequence]
    ind5 [sequence]

    fichier 2 :
    ind3 [sequence]
    ind4 [sequence]
    ind5 [sequence]
    Est-ce le format exact de tes deux fichiers? Sinon, prière de fournir un échantillon au format exact des fichiers en entrée.

    Citation Envoyé par lois_rancilhac Voir le message


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open(ind, '<', 'concat');
    my %concat=<ind>;
    print %concat;
    créé un tableau de hashage dont les clés sont les noms de mes individus (contenus dans le fichier concat).
    Très probablement pas. Tu ne peux pas remplir un hachage de cette manière, ou, au mieux, tu auras un hachage dans lequel les clefs seront les lignes impaires de ton fichier et les valeurs les lignes paires du fichier. Ce n'est certainement pas ce que tu veux.

    Il faut manipuler les lignes que tu lis afin d'en extraire deux champs qui formeront les paires clefs-valeurs de ton hachage. Là, pour t'aider, j'ai besoin du format exact de tes lignes en entrée.

    Par exemple, si ta ligne est stockée dans la variable $line et ressemble à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    une_clef;une_valeur
    et si tu as préalablement déclaré un hachage %concat, tu peux faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    my ($key, $val) = split /;/, $line;
    $concat{$key} = $val;
    A des fins de débogage, je te conseille fortement d'utiliser le module Data:: Dumper pour visualiser le contenu de tes structures de données (tableaux, hachages, etc.). En haut de ton programme, tu ajoutes la ligne suivante:
    Et, après avoir alimenté ton hachage %concat, tu peux ajouter la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    print Dumper \%concat;
    Cela te permettra de vérifier le contenu de ton hachage.

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    doctorant
    Inscrit en
    février 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Alpes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : doctorant

    Informations forums :
    Inscription : février 2018
    Messages : 4
    Points : 1
    Points
    1

    Par défaut

    Salut,

    merci pour ta réponse !

    l'exemple que j'ai mis représente bien l'architecture de mes fichiers de séquences (sauf qu'il y a plus d'individus, et plus de fichiers).
    Voilà un exemple de fichier de séquence:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    1488       CATCTCTCCAGCA--ACATCCGAGATAGCTACTCATCAGCAGCAACCACCCTCATnnnnCGTCAGAGGCCTAGCAAGAACGGAAGAACTTCTTTGATGGCTCCACCATGAGATGAAACG
    Neu73      CATCTCTCCAGCAGGACATCCGAGAAAGCTACTCATCAGCAGCAACCACCATCATnnnnCGTCAGAGGCCTAGCAAGAACGGAAGAACTTCTTTGATGGTTCCAACATGAGATGAAACG
    Neu83      CATCTCTCCAGCAAGACATCCGAGAAAGCTACTCATCAGCAGCAACCACCATCATnnnnCGTCAGAGGCCTAGCAAGAACGGAAGAACTTCTTTGATGGTTCCAACATGAGATGAAACG
    Neu84      CATCTCTCCAGCAAGACATCCGAGAAAGCTACTCATCAGCAGCAACCACCATCATnnnnCGTCAGAGGCCTAGCAAGAACGGAAGAACTTCTTTGATGGTTCCAACATGAGATGAAACG
    et je possède églament un fichier contenant seulement les noms de tous les individus présents dans les fichiers de séquences (en voici le début) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1488 
    And54 
    And57 
    Ap105 
    Ap106 
    Brk117 
    Brk120 
    BZ1 
    BZ16 
    Dej22 
    [...]
    Du coup je pensais créer un tableau de hachage dont chacun de mes individu est une clé, comme suit, sans leur attribuer de valeur au début. Ensuite j'ouvre mon premier fichier de séquences et attribue comme valeur à chaque individu du tableau de hachage la séquence corrspondante (lorsqu'un individu n'est pas reprśenté dans mon fichier de séquences, je lui attribue une suite de 'N'), comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ind1 [séquence_fichier1]
    ind2 [séquence_fichier1]
    ind3 NNNNNNNNNNNN
    ind4 NNNNNNNNNNNN
    ind5 [séquence_fichier1]
    [...]
    indN [séquence_fichier1]
    Ensuite , je répète l'opération avec mes n fichiers de séquences, de manière à obtenir quelque chose comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ind1 [séquence_fichier1/séquence_fichier2/.../séquence_fichiern]
    ind2 [séquence_fichier1/séquence_fichier2/.../séquence_fichiern]
    ind3 [NNNNNNNNNNNN/séquence_fichier2/.../séquence_fichiern]
    ind4 [NNNNNNNNNNNN/séquence_fichier2/.../séquence_fichiern]
    ind5 [séquence_fichier1/séquence_fichier2/.../séquence_fichiern]
    [...]
    indN [séquence_fichier1/séquence_fichier2/.../séquence_fichiern]
    J'espère que c'est plus clair, j'ai un peu de mal à l'expliquer...

    merci en tout cas pour tes explications, je vais essayer de faire ca diffŕement.

    bonne soirée
    Lois.

  4. #4
    Expert éminent Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    décembre 2012
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : décembre 2012
    Messages : 2 938
    Points : 8 233
    Points
    8 233

    Par défaut

    Bonjour,

    Ça ne serait pas plus simple de créer plutot une structure du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    perl -MData::Dumper -e '$xx{"foo"}[2]="titi";$xx{"bar"}[1]="toto"; print Dumper \%xx'
    $VAR1 = {
              'foo' => [
                         undef,
                         undef,
                         'titi'
                       ],
              'bar' => [
                         undef,
                         'toto'
                       ]
            };
    où l'indice (qui commence à zéro) serait le énième fichier ?
    Ici, par exemple,
    "foo" n'a pas de données dans le fichier 0 et 1 mais a des données dans le fichier 2.
    "bar" n'a pas de données dans le fichier 0 et 2 mais à des données dans le fichier 1.

    Tu n'aurais qu'a gérer un incrément (pour l'indice du énième fichier).
    Cordialement.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    doctorant
    Inscrit en
    février 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Alpes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : doctorant

    Informations forums :
    Inscription : février 2018
    Messages : 4
    Points : 1
    Points
    1

    Par défaut

    Salut,

    Merci beaucoup pour ta réponse. Effectivement, ca a l'air de bien coller à mes besoins. Juste deux petites questions : MData:umper est-il équivalent à Data:umper ? Et comment ce fait-il que tu puisses remplir le tableau xx sans l'avoir déclaré d'abord avec my ? (désolé si ces questions sont basiques, je débute)

    Cordialement,
    Lois

  6. #6
    Expert éminent Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    décembre 2012
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : décembre 2012
    Messages : 2 938
    Points : 8 233
    Points
    8 233

    Par défaut

    Ici, ce n'est qu'un pseudo-script oneliner en perl juste pour montrer à quoi ressemblerait la structure que je te proposais.

    Le -M, c'est pour dire au perl de charger un module avant l'execution du code, donc ici Data:: Dumper.

    Pour ce qui est du remplissage ou de l'utilisation de variables sans les déclarer d’abord, comme tu as pu le constater, on peut le faire mais il ne le faut pas, ici j'ai juste simplifié à l'extrême pour ne montrer que la partie intéressante.

    Comme ici, on peut le tolérer mais juste pour des petits onliner. Dés que c'est un vrai script, on le fait bien en utilisant les pragma 'strict' et 'warning' et on déclare ces variables.
    Cordialement.

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    doctorant
    Inscrit en
    février 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Alpes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : doctorant

    Informations forums :
    Inscription : février 2018
    Messages : 4
    Points : 1
    Points
    1

    Par défaut

    Bonjour à tous,

    Encore merci pour vos conseils. J'ai réussi à faire ce que je voulais, ce n'est sûrement pas la solution la plus élégante/simple mais ça fonctionne, donc je met mon script ici pour ceux qui pourraient en avoir besoin.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/perl
    use strict;
    use warnings;
    use Data::Dumper;
     
    open(LOCI, '<', '/home/lois_rancilhac/Documents/learning_perl/list_loci');
    my @loci;
    foreach my $t (<LOCI>) {
    	chomp $t;
    	push(@loci, $t);
    }
    Cette partie permet d'importer la liste des fichier de séquences que je veux traiter (elle sera générée en amont de ce script).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    open (LIST, '<', '/home/lois_rancilhac/Documents/learning_perl/list_ind');
    my @list_ind;
    foreach my $l (<LIST>) {
    	chomp $l;
    	push(@list_ind, $l);
    }
     
    my %tab_conc;
    for my $ligne (@list_ind) {
    	$tab_conc{"$ligne"} .= "1";
    }
    J'importe la liste de tous mes individus dans le tableau @list_ind, puis je créé un tableau de hachage %tab_conc dont les clés sont mes individus et je leur attribue à toutes la valeur "1" (valeur arbitraire, seulement pour pouvoir créer le tableau, je supprimerai les 1 en aval du script).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    for my $i (@loci) {
    	open(LOCUS, '<', "/home/lois_rancilhac/Documents/learning_perl/$i");
    	my %tab;
    	for my $ligne2 (<LOCUS>) {
    		my @locus_ligne=split('\s+', $ligne2);
    		my $indl2=$locus_ligne[0];
    		$tab{"$indl2"}=$locus_ligne[1];
    	}
    	my @k=keys(%tab);
    	my $N=length($tab{$k[1]});
    	for my $j (@list_ind) {
    	    if (defined($tab{"$j"})) { $tab_conc{"$j"} .= $tab{"$j"};}
    	    else {$tab_conc{"$j"} .= "N"x $N;}
    	}
    }
     
    open (OUTPUT, '>', "/home/lois_rancilhac/Documents/learning_perl/output");
    print Dumper \%tab_conc;
    print OUTPUT %tab_conc;
    close(OUTPUT);
    J'ouvre mes fichiers de séquences l'un après l'autre, les stocke dans un tableau de hachage. Ensuite, pour chaque individu, si il est représenté dans le fichier de séquences lu je concatène sa séquence dans le gros tableau %tab_conc, si il n'est pas présent je met à la place une suite de N de la longueur de la séquence.
    Ensuite j'écris le tableau %tab_concat dans un fichier. J'ai juste un problème avec cette dernière partie : dans mon fichier de sortie, j'obtiens toutes mes clés et valeurs sur la même ligne, sans séparation. Savez vous si il y a moyen d'exporter ca sous forme de tableau lisible (i.e clés et valeurs séparées et chaque couple (clé, valeur) sur une ligne différente) ?

    Cordialement,
    Lois

  8. #8
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    mai 2012
    Messages
    3 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : mai 2012
    Messages : 3 542
    Points : 12 192
    Points
    12 192
    Billets dans le blog
    1

    Par défaut

    Bonjour,

    pour la lecture de lignes depuis un descripteur de fichier, il vaut mieux utiliser while que for ou foreach. Donc, remplacer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    foreach my $t (<LOCI>) {
    	chomp $t;
    	push(@loci, $t);
    }
    par:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while (my $t = <LOCI>) {
    	chomp $t;
    	push(@loci, $t);
    }
    Et idem pour:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    foreach my $l (<LIST>) {
    # ...
    La différence entre les deux syntaxes se fait surtout sentir pour de gros fichiers, mais c'est tout de même plus efficace aussi pour de petits fichiers.

    Mais ne change pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    for my $ligne (@list_ind) {
    # ...
    c'est bien la syntaxe préférée pour lire les éléments d'un tableau.

Discussions similaires

  1. Concaténer des tableaux C# Linq
    Par persia dans le forum C#
    Réponses: 2
    Dernier message: 05/02/2016, 15h03
  2. Réponses: 2
    Dernier message: 29/08/2012, 17h59
  3. [Hash] table de hachage contenant des tableaux
    Par GLDavid dans le forum Langage
    Réponses: 4
    Dernier message: 19/01/2007, 18h03
  4. [Tableaux] Concaténation des éléments d'un tableau
    Par T0xF0x dans le forum Fonctions
    Réponses: 4
    Dernier message: 17/04/2006, 21h10
  5. free sur des tableaux "a moitié dynamiques"
    Par barthelv dans le forum C
    Réponses: 4
    Dernier message: 31/07/2003, 16h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo