IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Langage Perl Discussion :

comparaison deux tableaux


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut comparaison deux tableaux
    bonjour,
    je dispose de deux tableaux @tab1 et @tab2, je veux comparer leur contenu.
    pour chaque élèment du tableau @tab1 voir s'il existe dans @tab2, puis faire de même pour chaque élèment de @tab2.
    comment je peux faire ça en perl? y a t-il une fonction prédéfinie qui me permet de faire ça?
    Merci

  2. #2
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    non mais il y a des modules CPAN pour Array::Compare List::Compare et surement d'autres

  3. #3
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Bonjour,

    Je dirais que comme toujours en Perl, il y a plusieurs possibilités... Par exemple, en utilisant les hash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my %hash;
    foreach my $elem (@tab1)
    {
    	foreach (@tab2)
    	{
    		$hash{$elem}++ and last if ($elem eq $_);
    	}
    }
    Ensuite, pour savoir si un élément est dans les deux tableaux, tu fais un exists. Si l'élément est présent dans la table de hachage, il est dans les deux tableaux, sinon non.

    Ce n'est certainement pas la meilleure solution, juste la première à laquelle je pense.

    Sinon, comme le dit djibril, le mieux est encore d'utiliser des modules.
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  4. #4
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    merci pour votre aide, seulement pour afficher les elts de ma table de hachage, je fais:
    foreach(keys %hash)
    {
    print "$hash{$elem}\n";
    }

    ça me donne une ligne vide, ça n'affiche rien, bien que j'aie des tucs en commun.

    Merci

  5. #5
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Citation Envoyé par bezoindaidde
    merci pour votre aide, seulement pour afficher les elts de ma table de hachage, je fais:
    foreach(keys %hash)
    {
    print "$hash{$elem}\n";
    }

    ça me donne une ligne vide, ça n'affiche rien, bien que j'aie des tucs en commun.

    Merci
    Et bien je ne sais pas très bien ce que fait ton code, mais pas ce que tu veux à priori... Essaye plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    foreach(keys %hash)
    {
       print "$hash{$_}\n";
    }
    Mais le résultat, ça ne sera que des 1. En fait, avec mon système, tu te moques des valeurs de la table de hachage, tout ce qui est important, ce sont les clés. Si une clé existe dans la table de hachage, c'est que cette clé fait partie des deux tableaux.
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  6. #6
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    Oui, mais moi je voudrais justement rapporter dans mon logfile, les élèments qui ne sont pas en commun, voilà un simple exemple que j'ai écrit:

    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
    #!/bin/sh 
    eval "exec perl -x $0 $*"
    #!bin/perl
     
    push @tab1, "aaa","bbb 123","ccc 456","dd", "mmm pp";
    push @tab2, "eee","ccc 456"," kkk"," mmm pp","aaa";
     
    my %hash;
    foreach my $elem (@tab1)
    {
    	foreach (@tab2)
    	{
    		$hash{$elem}++ and last if ($elem ne $_);
    	}
    }
     
    foreach(keys %hash)
    {
    print "$hash{$elem}\n";
    }
    donc en principe dans la console, il devrait m'afficher:
    bbb 123 in @tab1 and not in @tab2
    dd in @tab1 and not in @tab2
    eee in @tab2 and not in @tab1
    kkk in @tab2 and not in @tab1

    voilà c'est juste un ptit code pour comprendre, mais c'est le résultat que je veux avoir.

    Merci

  7. #7
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par Woufeil
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my %hash;
    foreach my $elem (@tab1)
    {
    	foreach (@tab2)
    	{
    		$hash{$elem}++ and last if ($elem eq $_);
    	}
    }
    Mais ça c'est en O(n*m) alors qu'on peut faire du O(n+m) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    sub intersect (&\@\@) {
        my ($code, $a, $b) = @_;
        my %temp;
        @temp{map {$code->()} @$b} = ();
        return grep { exists $temp{$code->()} } @$a;
    }
    A utiliser ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my @a = (1, 2, 3);
    my @b = (3, 2, 5);
    my @dans_les_2 = intersect {$_} @a, @b;
    for my $i (@dans_les_2) {
      print "$i\n";
    }
    affiche :
    2
    3
    Le bloc qu'on fournit à intersect() sert à calculer une "string caractéristique" des éléments de @a et @b, autrement dit une chaîne de caractère telle que si les chaînes de caractères correspondantes à deux éléments sont égales, alors les éléments sont égals (du point de vue de notre intersection), dans la plupart des cas, {$_} devrait suffire.

    Pour utiliser cette fonction, soit mettez la dans un module que vous chargerez au début de votre script, soit mettez la dans votre script, mais n'oubliez pas alors de rajouter la ligne "sub intersect (&\@\@);" au début de votre script.

    --
    Jedaï

  8. #8
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Voici un exemple comme un autre qui fait ce que tu souhaites :

    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
    #!/usr/bin/perl
    use strict;
    use warnings;
     
    my @tab1 = ("aaa","bbb 123","ccc 456","dd", "mmm pp");
    my @tab2 = ("eee","ccc 456"," kkk"," mmm pp","aaa");
    my %hash;
     
    foreach(@tab1)
    {
        $hash{$_}[0] = 1;   # les valeurs de @tab1 sont rangées à l'indice 0
    }
    foreach(@tab2)
    {
        $hash{$_}[1] = 1;   # les valeurs de @tab2 sont rangées à l'indice 1
    }
     
    foreach(keys %hash)
    {
        if (! defined($hash{$_}[0]) || ! defined($hash{$_}[1]))
        {
            print "\"$_\" trouvé dans \@tab1 mais pas dans \@tab2\n" if (! defined($hash{$_}[1]));
            print "\"$_\" trouvé dans \@tab2 mais pas dans \@tab1\n" if (! defined($hash{$_}[0]));
        }
    }
    Résultat dans la console :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    "dd" trouvé dans @tab1 mais pas dans @tab2
    "mmm pp" trouvé dans @tab1 mais pas dans @tab2
    " mmm pp" trouvé dans @tab2 mais pas dans @tab1
    "eee" trouvé dans @tab2 mais pas dans @tab1
    "bbb 123" trouvé dans @tab1 mais pas dans @tab2
    " kkk" trouvé dans @tab2 mais pas dans @tab1

  9. #9
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par bezoindaidde
    Oui, mais moi je voudrais justement rapporter dans mon logfile, les élèments qui ne sont pas en commun
    Ok, dans ce cas la fonction subtract te conviendra mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    sub subtract (&\@\@) {
        my ($code, $a, $b) = @_;
        my %temp;
        @temp{map {$code->()} @$b} = ();
        return grep { not exists $temp{$code->()} } @$a;
    }
    A utiliser à peu près de la même façon que intersect(), mais effectue une soustraction ensembliste plutôt qu'une intersection, ton script deviendrait :
    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
    #!perl
    # modules and declarations
    use strict; use warnings;
    sub subtract (&\@\@);
     
    my @tab1 = ("aaa","bbb 123","ccc 456","dd", "mmm pp");
    my @tab2 = ("eee","ccc 456"," kkk"," mmm pp","aaa");
     
    # main
    for my $nin2 ( subtract {$_} @tab1, @tab2 ) {
      print "<$nin2> in \@tab1 and not in \@tab2.\n";
    }
    for my $nin1 ( subtract {$_} @tab2, @tab1 ) {
      print "<$nin1> in \@tab2 and not in \@tab1.\n";
    }
     
    # subroutines
    sub subtract (&\@\@) {
        my ($code, $a, $b) = @_;
        my %temp;
        @temp{map {$code->()} @$b} = ();
        return grep { not exists $temp{$code->()} } @$a;
    }
    __END__
    --
    Jedaï

  10. #10
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Grillé 3 fois, pas mal :p Je laisse quand même, mais je précise que je répondais à bezoindaidde

    Ton script ne fonctionne pas, il va mettre tous les éléments de @tab1 (sauf le premier si c'est le même que dans @tab2) comme clé du hash. Le script que tu demandes est un peu plus complexe, et mieux vaut utiliser le module que te conseille djibril : Array::Compare et la méthode full_compare :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $comp = Array::Compare->new();
    my @dif = $comp->full_compare(\@tab1, \@tab2);
    Ton tableau @dif contiendra les indices des éléments qui différent entre les deux tableau.

    €dit : Jedai, comme je disais, ce n'étais pas du tout la meilleure solution, juste la première à me venir à l'esprit
    Effectivement, la tienne est bien meilleure !
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  11. #11
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    rhaaaaaaa !!!

    Z'avez tous répondu en même temps que mon p'tit script qui fait ce que Bezoindaide veut

    purée, pour une fois que j'fais un truc bien

  12. #12
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par Woufeil
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $comp = Array::Compare->new();
    my @dif = $comp->full_compare(\@tab1, \@tab2);
    A vrai dire ça ne marche pas trop... Parce que Array::Compare tient compte de l'ordre des éléments. En réalité, bezoindaidde est plutôt en train de travailler sur des ensembles que sur des tableaux, en tant que tel, il devrait plutôt utiliser des hashs que des tableaux, ou même Set::Array qui contient tout le nécessaire pour arriver à ses fins :
    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
    #!perl
    # modules and declarations
    use strict; use warnings;
    use Set::Array;
     
    my $tab1 = Set::Array->new("aaa","bbb 123","ccc 456","dd", "mmm pp");
    my $tab2 = Set::Array->new("eee","ccc 456"," kkk"," mmm pp","aaa");
     
    # main
    for my $nin2 ( $tab1->difference($tab2) ) {
      print "<$nin2> in \@tab1 and not in \@tab2.\n";
    }
    for my $nin1 ( $tab2->difference($tab1) ) {
      print "<$nin1> in \@tab2 and not in \@tab1.\n";
    }
    --
    Jedaï

  13. #13
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Citation Envoyé par Jedai
    A vrai dire ça ne marche pas trop... Parce que Array::Compare tient compte de l'ordre des éléments. En réalité, bezoindaidde est plutôt en train de travailler sur des ensembles que sur des tableaux, en tant que tel, il devrait plutôt utiliser des hashs que des tableaux, ou même Set::Array qui contient tout le nécessaire pour arriver à ses fins :
    Oups, je n'avais pas pris en compte ce "détail"... Effectivement, si l'ordre n'est pas important, les hashs ou comme tu dis le module Set::Array semble plus approprié.

    Désolé de mon erreur
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  14. #14
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Citation Envoyé par bezoindaidde
    Merci Jedai pour ta réponse, mais ce que je cherche comme je l'ai précise dans mon précédent post, c plutôt d'afficher les éléments qui ne sont pas en commun, pas le contraire !

    union peut faire l'affaire dans ce cas là??
    Cherche ma réponse à 14h02 noyée parmi d'autre au-dessus, mon script fait exactement ce que tu souhaites (je finirai bien par y arriver )

Discussions similaires

  1. PL/SQL COMPARAISON DE DEUX TABLEAUX APRES BULK
    Par mimi_été dans le forum PL/SQL
    Réponses: 5
    Dernier message: 30/06/2009, 12h14
  2. Comparaison de deux tableaux
    Par tibss dans le forum Excel
    Réponses: 1
    Dernier message: 06/05/2009, 21h30
  3. Comparaison de deux tableaux en VB6
    Par taille50 dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 10/08/2007, 10h28
  4. Comparaison de deux tableaux
    Par solorac dans le forum Excel
    Réponses: 7
    Dernier message: 03/08/2007, 08h49
  5. Comparaison de deux tableaux
    Par siaoly dans le forum Langage
    Réponses: 5
    Dernier message: 27/06/2006, 19h40

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