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 :

Difference/similitudes entre 2 chaine de caracteres


Sujet :

Langage Perl

  1. #1
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2015
    Messages : 43
    Points : 37
    Points
    37
    Par défaut Difference/similitudes entre 2 chaine de caracteres
    Bonjour,

    je voudrais comparer 2 chaines de caracteres et en extraire les similitudes et les différences.

    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $chaine1 = "ma toute premiere chaine ";
    $chaine2 = "ma deuxieme chaine ";
    me renverrait idéalement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    @similitudes = (ma,chaine)                     # commun entre chaine 1 et chaine2
    @difference_chaine1 = (toute,premiere)   #ce qui est ajouté à la chaine 1
    @difference_chaine2 = (deuxième)          #ce qui est ajouté à la chaine 2
    Connaissez-vous une méthode pour faire ça ?

    Merci d'avance !

  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 612
    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 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    tu veux faire l'analyse par mots entiers, ou aussi par morceaux de mots?

    Et l'ordre des mots est-il important?

  3. #3
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2015
    Messages : 43
    Points : 37
    Points
    37
    Par défaut
    Bonjour,

    Effectivement, mieux vaut préciser : l'ordre n'est pas important.

    1) Je pensais à l'origine travailler sur les mots entiers (plus simple !) . En fait, l'idée c'est que si je compare des chaines telles que :

    chaine 1 = "ou globules blancs"
    chaine 2 = "globules blancs"
    chaine 3 = "globules"

    correspondant à la définition de "leucocytes",

    je vois que "globules " et "blancs" apparaissent 2 fois ensemble, donc je supprime la troisième chaine car je la considère incomplète.

    Après, en comparant les chaines 1 et 2, sachant que le mot "ou" n'est pas porteur d'information ça me donnera "leucocytes = globules blancs".

    2) Si je pouvais découper les mots en préfixes/suffixes ce serait encore mieux, mais la mise en oeuvre me semble bien plus complexe.

    Dans ce cas, pour la définition "arthrite =
    chaine 1 = inflammation des articulations
    chaine 2 = = inflammation articulatoire
    chaine 3 = inflammation"

    Ici je pourrais considérer que chaine 1 = chaine 2 (de simples variantes puisque les 2 sont correctes, rien n'est manquant ni superflu) en partant du principe que je peux substituer un déterminant + nom (articul-ation) par un adjectif (articul-atoire) formé sur le même préfixe que le nom.

    J'espère que c'est assez clair

  4. #4
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    je me lance, c'est sans doute pas optimum mais ça fonctionne comme décrit plus haut (c'est surtout histoire de manip un peu perl le vendredi matin ) :
    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
    use Data::Dumper;
     
    my $chaine1 = "ma toute premiere chaine";
    my $chaine2 = "ma deuxieme chaine";
     
    my @tab1 = split / /, $chaine1;
    my @tab2 = split / /, $chaine2;
    my ($s1, $s2, $diff1, $diff2);
    my (@similitudes, @differences_chaine1, @differences_chaine2);
     
    if (@tab1 < @tab2) { # on se base sur la chaine la plus courte
            ($s1, $s2, $diff1, $diff2) = (\@tab1, \@tab2, \@differences_chaine1, \@differences_chaine2);
    } else {
            ($s1, $s2, $diff1, $diff2) = (\@tab2, \@tab1, \@differences_chaine2, \@differences_chaine1);
    }
     
    foreach my $i (@{$s1}) {       # pour chaque mot de la chaine la plus courte
       if (grep /^$i$/, @{$s2}) {  # si il existe dans l'autre chaine
          push @similitudes, $i;   # on l'ajoute aux similitudes
       } else {
          push @{$diff1}, $i;      # sinon aux differences de la chaine la plus courte
       }
    }
     
    foreach my $j (@{$s2}) {              # pour chaque mot de la chaine la plus longue
       if (! grep /^$j$/, @similitudes) { # si il n'est pas dans les similitudes
          push @{$diff2}, $j;             # c'est qu'il est dans les differences de la chaine la plus longue
       }
    }
     
    print "=== similitudes : ===\n" . Dumper \@similitudes;
    print "=== differences chaine1 : ===\n" . Dumper \@differences_chaine1;
    print "=== differences chaine2 : ===\n" . Dumper \@differences_chaine2;
    et l'exécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    === similitudes : ===
    $VAR1 = [
              'ma',
              'chaine'
            ];
    === differences chaine1 : ===
    $VAR1 = [
              'toute',
              'premiere'
            ];
    === differences chaine2 : ===
    $VAR1 = [
              'deuxieme'
            ];

  5. #5
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2015
    Messages : 43
    Points : 37
    Points
    37
    Par défaut
    Super,

    Merci BufferBob ça va me permettre d'avancer.

    Juste une dernière question : s'il y a plus de 2 chaines à comparer, plutôt que comparer chaque tableau par 2 par 2, est-ce qu'on peut faire un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @pluspetitechaine = ????? (@tab1,@tab2,@tab3,...)
    Bonne journée

  6. #6
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 276
    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 : 4 276
    Points : 12 717
    Points
    12 717
    Par défaut
    Bonjour,
    Une solution similaire avec des hash:
    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
    use Data::Dumper;
     
    my $chaine1 = "ma toute premiere chaine";
    my $chaine2 = "ma deuxieme chaine";
    my %similitudes;
    my %hash1,%hash2;
    my $var1,$var2;
    $hash1{$_}=1 foreach (split / /, $chaine1);
    $hash2{$_}=1 foreach (split / /, $chaine2);
    ($var1,$var2) = keys (%hash1) > keys %hash2 ? (\%hash1,\%hash2) : (\%hash2,\%hash1);
     
    foreach (keys %$var1){
            if($$var2{$_} == 1){
                    $similitudes{$_}=1;
                    delete $hash1{$_};
                    delete $hash2{$_};
            }
    }
     
    print "=== similitudes : ===\n" . Dumper \%similitudes;
    print "=== differences chaine1 : ===\n" . Dumper \%hash1;
    print "=== differences chaine2 : ===\n" . Dumper \%hash2;
    Ce qui donne à l'execution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    === similitudes : ===
    $VAR1 = {
              'chaine' => 1,
              'ma' => 1
            };
    === differences chaine1 : ===
    $VAR1 = {
              'premiere' => 1,
              'toute' => 1
            };
    === differences chaine2 : ===
    $VAR1 = {
              'deuxieme' => 1
            };
    Cordialement.

  7. #7
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    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 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Nonjour,

    j'utiliserais aussi des hachages, mais un peu différemment:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    use strict; use warnings;
     
    my $chaine1 = "ma toute premiere chaine";
    my $chaine2 = "ma deuxieme chaine";
    my %words1 = map { $_ => 1 } split / /, $chaine1;
    my %words2 = map { $_ => 1 } split / /, $chaine2;
     
    my @similitudes = grep { exists $words1{$_} } keys %words2;
    my @diff1 = grep { not exists $words1{$_} } keys %words2;
    my @diff2 = grep { not exists $words2{$_} } keys %words1;
     
    print "Similitudes: @similitudes \n";
    print "Diff 1: @diff1 \n"; 
    print "Diff 2: @diff2 \n";
    Ce qui imprime:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Similitudes: chaine ma
    Diff 1: deuxieme
    Diff 2: premiere toute

  8. #8
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 276
    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 : 4 276
    Points : 12 717
    Points
    12 717
    Par défaut
    Eh ben, j'ai encore des progrès à faire...

    Voici tout de même ma version corrigée qui devrait en principe être plus rapide par rapport à ma première version:
    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
    use strict;
    use warnings;
    use utf8;
     
    use Data::Dumper;
     
    my $chaine1 = "ma toute premiere chaine";
    my $chaine2 = "ma deuxieme chaine";
    my (%similitudes,%diff1,%diff2);
    %diff1= map { $_ => 1 } (split / /, $chaine1);
    foreach (split / /,$chaine2){
       if(not exists $similitudes{$_}){
           if(exists $diff1{$_}){
               $similitudes{$_}=1;
               delete $diff1{$_};
           }
           else{
               $diff2{$_}=1;
           }
       }
    }
     
    print "=== similitudes : ===\n" . Dumper \%similitudes;
    print "=== differences chaine1 : ===\n" . Dumper \%diff1;
    print "=== differences chaine2 : ===\n" . Dumper \%diff2;
    Cordialement.

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    La question initiale semble faire appel à des notions de linguistique. Peut-être que les propositions faites gagnerons à utiliser un module CPAN linguistique (avec la locale positionnée à FR), comme par exemple Lingua::Stem.

    Une autre approche, en utilisant le module WordNet::Similarity (mais j'ai peur que même s'il existe une base de donnée pour le français, le Wolf, elle ne soit pas accessible depuis ce module).

    On pourrait aussi s'inspirer de la distance de Levenshtein : Levenshtein::Distance
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

Discussions similaires

  1. [XL-2000] Evaluer la similitude entre 2 chaines de caractères
    Par Monjarno dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 07/07/2010, 08h35
  2. supprimer texte entre deux chaine de caractere
    Par fadoch dans le forum C++
    Réponses: 7
    Dernier message: 14/01/2010, 16h59
  3. Réponses: 1
    Dernier message: 02/12/2009, 16h18
  4. Recherche API indiquant differences entre chaines de caracteres
    Par julseb2007 dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 14/08/2007, 14h24
  5. Réponses: 7
    Dernier message: 03/02/2006, 13h50

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