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 PHP Discussion :

Comparaison de deux textes mot à mot


Sujet :

Langage PHP

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut Comparaison de deux textes mot à mot
    Bonjour, j'espère que vous avez passé un bon week-end.

    Voilà je me demandais si quelqu'un ici avait déjà eu à coder une méthode permettant de comparer deux textes en PHP mot à mot. Et ceci sans prendre compte de l'ordre des similarités. C'est assez difficile à expliquer.

    Voici un exemple :
    Phrase 1 : Il est beau le soleil à la page.
    Phrase 2 : Ici, on dit qu'il est beau le soleil.

    En gros je voudrais quelque chose qui remarque ce genre de concordance. Du moment ou minimum un couple de mots est en commun dans les 2 textes quoi...

    J'ai bien une idée d'algo :

    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
    // On découpe les textes en mots
    $parsedfirstText = splitStringBySpaces($firstText);
    $parsedSecondText = splitStringBySpaces($secondText);
     
    // On compare mot à mot les textes
    foreach ($parsedfirstText as $wordOfFirstText) {
        foreach ($parsedSecondText as $wordOfSecondText) {
            // Ici ça se complique...
            // On peut à la limite les comparer
            if($wordOfFirstText == $wordOfSecondText) {
                // Ensuite il faudrait une boucle je pense, un while, tant qu'ils sont égaux, on continue à avancer dans les deux textes et à comparer mot à mot
                // Mais c'est après que je sèche...
            }
        }
    }
    j'ai déjà essayé les fonctions de type levenshtein et similar_text. Elles compare caractère par caractère. Je voudrais comparer du mot à mot.
    Je donne à nouveau des exemples :

    Le soleil brille de mille feux ce soir. Je pense que je vais sortir en bateau de croisière pour en profiter.
    Le bateau de croisière sort ce soir sous ce soleil qui brille de mille feux.

    En gros, je voudrais identifier tous les groupes de mots de plus de deux mots de longueur présent dans les deux textes. Voilà je crois que bien résumé, en une phrase c'est ça l'idée, si je dis pas de bêtises xD Peu importe l'ordre d'apparition dans les texte de ces "groupes".

    Merci, d'avance !

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 84
    Points : 101
    Points
    101
    Par défaut
    Salut,

    Il faut que tu passes par une expression reguliere :

    exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    //txt de base
    $subject = "abcdef";
    //ce que tu recherches
    $pattern = '/^def/';
    preg_match($pattern, substr($subject,3), $matches, PREG_OFFSET_CAPTURE);
    echo '<pre>';
    print_r($matches);
    echo '</pre>';
    ?>
    ++
    zwaldo

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Quoi ? Non tu n'as pas compris. Pourtant mon explication est très clair. Je ne connais pas les motifs à rechercher. Je cherche juste à savoir justement les groupes de mots (de minimum 2 mots se suivant) qui sont commun au deux textes.

  4. #4
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Moi je ferai un truc comme ça:
    J'utilise une pattern placée dans un lookahead (test avant) pour obtenir la plus grande correspondance possible au départ de chaque mot, même si le correspondances se chevauchent. Ensuite je filtre les résultats pour ne récupérer que les correspondances les plus grandes (i.e: pour "il fait beau", j'élimine le résultat "fait beau")

    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
    $pattern = '~(?=(\b\w+(?>\W+\w+)+\b).*\b(\1)\b)~ius';
     
    if (preg_match_all($pattern, $texte, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
     
        $last_match_end_offset = -1;
        $result = array();
     
        foreach($matches as $k => $v) {
            if ( $last_match_end_offset < $match_end_offset = mb_strlen($v[1][0]) + $v[1][1] ) {
                $last_match_end_offset = $match_end_offset;
                $result[] = array('excerpt' => $v[1][0], 'offset1' => $v[1][1], 'offset2' => $v[2][1]);
            }
        }
        unset($matches);
        print_r($result);
    }
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    CosmoKnacki, tout d'abord merci pour ta réponse qui à l'air pas mal recherché, et surtout pour les explications allant avec.
    Mais j'avoue ne pas tout comprendre.
    On parle bien ici de la comparaison de 2 textes n'est ce pas ? Je comprends pas à quel moment tu compares le 1er avec le 2ème. En fait tout simplement je crois que c'est ton pattern qui m'échappe ^^

    EDIT: Après avoir testé ta méthode, c'est bien ça j'avais bien compris finalement. Tu compares le texte avec lui même. Enfin tu compares chaque mot du texte sur le texte quoi. Du coup je vais faire une boucle sur chaque mot du texte 1 et utiliser ta méthode sur le texte 2, ça semble correct, non ? Le seul problème c'est que je ne sais pas comment modifier ton pattern pour faire ça xD Je m'y met ^^

    EDIT 2 : C'est normal également que dès que mon texte est trop long. Ça ne marche plus, ne me retourne plus rien... Oo Ca par contre je sais pas pourquoi, je vais pas pouvoir le gérer seul

  6. #6
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Désolé, effectivement, j'étais partie sur "comparer le texte avec lui même". Ce qui n'est pas adapté pour ce que tu cherches à faire (comparer deux textes différents).

    Cela dit, je ne suis pas étonné qu'au delà d'une certaine longueur de texte ton PC explose. Il faut procéder autrement.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  7. #7
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Citation Envoyé par 0.GeGe.0 Voir le message
    EDIT 2 : C'est normal également que dès que mon texte est trop long. Ça ne marche plus, ne me retourne plus rien... Oo Ca par contre je sais pas pourquoi, je vais pas pouvoir le gérer seul
    L'affichage des erreurs PHP est-il activé ?
    Vérifies notamment la durée maximum d'exécution d'un script autorisée par ton php.ini (de base 30secondes) et la mémoire RAM maximale allouée au script (de même c'est dans le php.ini).

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Oui pas de limite de temps, pas de limite de mémoire et mes erreurs sont affichés.
    ça me retourne juste rien, dès que mon texte dépasse un certain nombre de caractères (et pas beaucoup en plus, une quinzaine de phrases environ).

    EDIT :

    Par exemple sur ça, ça marche parfaitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Le soleil brille de mille feux ce soir. Je pense que je vais sortir en bateau de croisière pour en profiter.
    En cinquante ans, grâce à des efforts considérables dans la recherche et l’élaboration de fusion, la performance des plasmas a été multipliée par 10’000. La fission, connue de tous, consiste à « casser » les atomes lourds comme l’uranium pour libérer des neutrons énergétiques.
    Dans les étoiles, la gravitation permet de crée les conditions nécessaires à la fusion. Sur notre soleil, plus précisément en son cœur, la température atteint 15 millions de degrés. A cette température-là, la barrière que les forces électrostatiques dressent entre les charges électriques positives des atomes d’hydrogène n’est plus assez forte pour empêcher les noyaux de fusionner pour donner naissance à un atome d’hélium. Le soleil brille.
    Et en rajoutant juste une phrase à la fin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Le soleil brille de mille feux ce soir. Je pense que je vais sortir en bateau de croisière pour en profiter.
    En cinquante ans, grâce à des efforts considérables dans la recherche et l’élaboration de fusion, la performance des plasmas a été multipliée par 10’000. La fission, connue de tous, consiste à « casser » les atomes lourds comme l’uranium pour libérer des neutrons énergétiques.
    Dans les étoiles, la gravitation permet de crée les conditions nécessaires à la fusion. Sur notre soleil, plus précisément en son cœur, la température atteint 15 millions de degrés. A cette température-là, la barrière que les forces électrostatiques dressent entre les charges électriques positives des atomes d’hydrogène n’est plus assez forte pour empêcher les noyaux de fusionner pour donner naissance à un atome d’hélium. Le soleil brille. Au cours de la transformation, il y a une perte de masse entre les atomes d’hydrogène et l’atome d’hélium résultant.
    Cela me retourne un tableau vide

    Après des tests, en fait je ne rentre pas dans le if du preg_match_all, c'est le pattern qui est trop gros au bout d'un moment quand il y a trop de mots (caractères séparés par des espaces) du coup ça foire tout. :'(

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Oh grand maître des regex CosmoKnacki , viens moi en aide je t'en prie.

    En attendant vu que je n'ai pas trouvé de façon pour le faire avec des patterns et regex, je suis parti sur de la manip' de tableaux.

    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
     
     
    function lolCompare($firstText, $secondText, $threshold = 2) {
        // On enlève la ponctuation /!\ fausse les offsets et les tailles.
        $firstText = removePunctuations($firstText);
        $secondText = removePunctuations($secondText);
        // On explose les strings et on récupère les mots communs.
        $commonWords = array_intersect(explode(' ', $firstText), explode(' ', $secondText));
     
        $compoundWord = '';
        $result = array();
        $sequenceNumber = 1; // Numéro de séquence.
        foreach ($commonWords as $word) {
            $compoundWord.= $word . ' '; // On concatène $word avec $compoundWord et on rajoute un espace.
            $h = rtrim($compoundWord); // Pour une parfaite comparaison on copie $compoundWord et on supprime le "dernier" espace.
            if (substr_count($firstText, $h) && substr_count($secondText, $h)) { // on vérifie que la séquence existe dans les 2 textes.
                if (wordCount($h) >= $threshold) {
                    $result[$sequenceNumber] = $h;
                }
            } else {
                // On récupère le dernier mot après le "dernier espace" contenu dans $h (celui qui fait que substr_count($d, $h) === 0) et on re-initialise $compoundWord avec
                $compoundWord = ltrim(strrchr($h, ' ')) . ' ';
                // Ici l'incrémentation de $sequenceNumber correspond à une nouvelle clef (une nouvelle séquence de mots se suivant)
                $sequenceNumber++;
            } // Seule la sèquence la plus longue sera retenue puisque les précédentes seront écrasées.
        }
        display(array_values($result));
    }
    Mon gros problèmes c'est la ponctuation, si je la laisse "ce soir" ne match pas avec "ce soir." logique, et si je l'enlève, en plus de fausser les offsets et les tailles des chaînes, il match sur des trucs du genre "il fait beau. Je t'aime" parce que pour lui c'est "Il fait beau je t'aime". Enfin ce dernier point est dur à expliquer, il faut vraiment essayer pour comprendre. Sur des petites phrases c'est bon, mais sur un textes entiers ça fait des bugs des fois. Et puis de toute façon je ne veux pas dégrader l'information du texte et donc garder les accents.

    Merci de votre aide !

  10. #10
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Citation Envoyé par 0.GeGe.0 Voir le message
    Mon gros problèmes c'est la ponctuation, si je la laisse "ce soir" ne match pas avec "ce soir." logique, et si je l'enlève, en plus de fausser les offsets et les tailles des chaînes, il match sur des trucs du genre "il fait beau. Je t'aime" parce que pour lui c'est "Il fait beau je t'aime". Enfin ce dernier point est dur à expliquer, il faut vraiment essayer pour comprendre. Sur des petites phrases c'est bon, mais sur un textes entiers ça fait des bugs des fois. Et puis de toute façon je ne veux pas dégrader l'information du texte et donc garder les accents.
    Merci de votre aide !
    Tu peux essayer en partant sur un algo à tableau multi-dimension.
    A savoir donc faire une première découpe par phrase.
    Restera plus que les ponctuations de type virgule comme souci.

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  11. #11
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Je ne suis pas grand maître de quoi que ce soit, mise à part de la pintade farcie (qu'on se le dise).

    Si la solution que j'ai proposée plus haut (en l'adaptant pour deux textes différents) ne fonctionne pas dés qu'un texte est un peu long, c'est par ce que la pattern utilisée génère énormément de backtracking et nécessite beaucoup d'étapes pour trouver des correspondances. Ce qui fait que la recherche est tout simplement abandonnée, car la limite de backtracking est atteinte, sic var_dump(preg_last_error()); qui renvoie 2, ce qui est la valeur de la constante PREG_BACKTRACK_LIMIT_ERROR. (J'ai même fait des essais en limitant le nombre de mots, en utilisant des quantificateurs possessifs, mais rien n'y fait, la complexité explose à partir d'une certaine taille de texte, et une taille pas grande en plus).

    Clairement ce problème ne peut être résolu avec une simple pattern et ce, quelque soit sa sophistication. Ça n'exclue pas d'y recourir, mais dans ce cas, ça ne peut pas être le cœur même de l'algorithme.

    J'ai une idée (embryonnaire) d'approche faisant appel à un pré-traitement pour constituer une sorte de dictionnaire de pairs de mots avant la dite recherche, afin de la réduire au maximum.

    En tout cas, c'est vraiment un sacré challenge car il existe plusieurs algorithmes efficaces pour retrouver un chaîne dans une autre (Boyer-Moore, Aho-Corasick ...) mais ceux-ci n'exploitent pas le fait qu'on manipule des mots entiers.

    Si j'ai bien compris, tu cherches à faire une recherche de 2 mots minimum en ignorant la casse, éventuellement en ignorant les espaces superflus, mais en prenant en compte tout le reste (accents, ponctuation, symboles...) et puis à restituer les deux chaînes tel qu'elles se présentent dans leurs textes respectifs avec leurs positions.

    Si j'ai le temps j'essaierai de mettre en œuvre cette idée et si j'obtiens quelque chose je te tiendrai au courant. En tous les cas c'est un problème intéressant.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  12. #12
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Oui, c'est tout à fait ça t'as compris. En fait c'est tout bêtement un algo de comparaison de deux textes. Quelles sont leur parties communes ?

    Pour l'instant j'ai vraiment une comparaison mot à mot, donc de complexité O(n^2/2), c'est très vite lourd, long et horrible xD

    Je passe ma journée de demain (enfin aujourd'hui du coup) à étudier (et coder) les algos dont tu parles :
    http://fr.wikipedia.org/wiki/Algorit...us-cha%C3%AEne


    Merci pour ton intérêt en tout cas

  13. #13
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Bonjour,

    je souhaiterai prendre part à ce petit défi en proposant une soluce en 40 lignes de code basée sur l'intersection de tableaux :
    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
    <?php
     
    $a = 'Le soleil brille de mille feux ce soir. Je pense que je vais sortir en bateau de croisière pour en profiter.';
    $b = 'Le bateau de croisière sort ce soir sous ce soleil qui brille de mille feux.';
     
    // signes de ponctuations et autres symboles à supprimer
    $signes = ['.', ',', '!', '?', '«', '»', '"', "'"];
    $x      = str_replace($signes, '', $a);
    $y      = str_replace($signes, '', $b);
     
    // purge les espaces intempestifs
    $wx = array_filter(explode(' ', $x), 'strlen');
    $wy = array_filter(explode(' ', $y), 'strlen');
     
    $intersect = array_intersect($wx, $wy);
    $common    = [];
    $ci        = 0;
     
    foreach ($intersect as $k => $word)
    {
        unset($intersect[$k]);
     
        if ($k === 0)
        {
            $sentence = $word;
            continue;
        }
     
        $sentence .= ' '.$word;
     
        if (stripos($y, $sentence) !== false)
        {
            $common[$ci] = $sentence;
        }
        else
        {
            ++$ci;
            $sentence = $word;
        }
    }
     
    print_r($common);
     
    ?>
    Je pense que c'est améliorable. Il faudrait aussi voir la gestion des accents.
    Mais bon 0.GeGe.0 étant étudiant, il va devoir s'y coller tout seul

  14. #14
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Merci pour votre enthousiasme à tous, je pensais pas proposer un tel défis et surtout que ça allait intéresser autant.

    rawsrc : Il me suffit de lire les premières lignes de ton code pour voir que cela ne me satisfait pas MDR, je veux rien supprimer, et surtout pas la ponctuation.

    Mais c'est bon vous inquiétez pas, je suis sur la bonne voie.

  15. #15
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par 0.GeGe.0 Voir le message
    rawsrc : Il me suffit de lire les premières lignes de ton code pour voir que cela ne me satisfait pas MDR, je veux rien supprimer, et surtout pas la ponctuation.
    Très drôle...
    Tu n'as pas bien lu, le retrait de ces éléments n'a d'utilité que pour l'algo de recherche.Tu peux tout à fait conserver le texte initial une fois les données communes trouvées.

  16. #16
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Voici ce que cela donnerait :
    (à ajouter à la fin du code précédent)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $get_color = function() { return sprintf('#%06X', mt_rand(0, 0xFFFFFF)); };
     
    // affichage
    foreach ($common as $v)
    {
        $format = <<<html
    <span style="color:{$get_color()};">{$v}</span>
    html;
        $a = str_replace($v, $format, $a);
        $b = str_replace($v, $format, $b);
    }
     
    echo $a, '<br>', $b;

  17. #17
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    J'ai très bien compris et j'ai bien lu. Le problème en enlevant la ponctuation pendant la phase de recherche, c'est que tu fais de la recherche sans ponctuation... Logique, mais je te montre par un exemple ce que je veux te faire comprendre par là.

    Voici les deux textes à comparer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $texte1 = "Il fait beau. J'aime le chocolat. blanc comme le linge.";
    $texte2 = "Il ne sait pas que j'aime le chocolat blanc comme le linge.";
    Et voici ce que retourne ta fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Array ( [1] => le chocolat blanc comme le linge )
    Or le point change tout ! Une comparaison correcte aurait été :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Array ( [1] => le chocolat )
    Array ( [2] => blanc comme le linge )
    Et ceci n'est que pour te démontrer le point faible de ton algo, ici ça n'a pas grande importance (bien que dénaturant déjà le texte original) mais il y aura des cas où cela faussera tout.

    D'ailleurs ton dernier message avec la coloration, met super bien le problème en évidence :
    • Il fait beau. J'aime le chocolat. blanc comme le linge.
    • Il ne sait pas que j'aime le chocolat blanc comme le linge.

    Aucune coloration pour le premier extrait.



    PS : Selon la version de PHP on peut obtenir une Parse Error pour ta façon de déclarer les tableaux il me semble... On devrait pas préférer array() plutôt que [] ?

  18. #18
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    J'en avais bien conscience de ce problème en cas de prise en compte de la ponctuation mais bon mon but c'était de poser une idée d'algo de traitement histoire de te mettre sur une piste.
    Je ne vais pas le modifier mais sache qu'il est tout à fait possible de tenir compte de la ponctuation dans mon algo et même de sélectionner ce qui est utile ou pas.
    Je vais te laisser phosphorer dessus.

    En tout cas, si tu te mets pas à comparer deux bibles, je pense qu'en terme de perfs cette approche devrait tenir la route.

    Bonne continuation.

    PS : le support de la branche PHP 5.3 a été arrêté en juillet 2013, vu que je code exclusivement sur des versions récentes, j'ai pris l'habitude d'utiliser la notation courte pour les tableaux. Donc oui, il faut reprendre certains bouts de scripts.

  19. #19
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2012
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Merci pour ce complément, ainsi que pour ta participation

  20. #20
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Bon, voilà un petit script qui pourra t'aider. L'idée est de manipuler des "dictionnaires" (un pour chaque texte) qui sont en fait des tableaux à plusieurs dimensions dont les clefs sont des pattern et qui contiennent toutes les positions en octet de ces patterns dans les deux textes ainsi que les positions pour chaque troisième mot.
    Pourquoi des patterns et pas de simples chaînes?
    Pour deux raisons:
    • La première est qu'une pattern permet d'exprimer facilement le fait que
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      $str1 = "Liliane aime les saucisses, Maurice préfère la brandade.";
      est la même chose que
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      $str2 = "liLiaNE    aime LES sAucissES,  maurice PRÉfère     LA brandADE.";
      en ignorant casse et espaces. Ce qui permet d'utiliser array_intersect_key pour trouver les clefs communes.
    • La deuxième est qu'avec cette pattern et l'offset on peut très rapidement trouver le mot suivant dans le texte.


    La partie traitement consiste essentiellement à vider les dictionnaires et à éventuellement remplir le tableau de résultat.
    Pour chaque clef, on stocke les offsets quand il n'y a pas de mot suivant en commun dans le tableau de résultat, et pour chaque mot suivant on créé une nouvelle entrée dans le dictionnaire dont la clef sera "ancienne clef + mot suivant" (quand je dis "mot suivant" en fait je pense à un truc comme ça \s+mot ou comme ça ;\s+mot)
    Pour chaque nouvelle entrée créée, il faut ajouter les mots suivants possibles (pour recréer la structure à l'identique).
    C'est là que l'aspect pattern de la clef intervient. Comme il est impossible d'ancrer la pattern, la ruse consiste à utiliser le 5e paramètre de preg_match qui permet de préciser l'offset de départ pour la recherche et évidemment cet offset on le connait.

    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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    <meta charset="UTF-8"/><pre><?php
    ini_set('diplay_errors', 'On');
    mb_internal_encoding("UTF-8");
     
    define('FILENAME1', './text_files/xaa');
    define('FILENAME2', './text_files/xab');
     
    // chargement des fichiers
    $txt1 = file_get_contents(FILENAME1);
    $txt2 = file_get_contents(FILENAME2);
     
    // on fait une copie en lowercase
    $txt1_lc = mb_strtolower($txt1);
    $txt2_lc = mb_strtolower($txt2);
     
    // construction des dictionaires
    function build_dict(&$dict, $str) {
        $dict = array();
        $arr = preg_split('~\b~u', $str);
        $offset = strlen(array_shift($arr));
        $m_size = count($arr);
     
        $length = array_map('strlen', $arr);
        $arr = preg_replace('~\s+~u', '\s+', $arr);
     
        for ($i=0; $i<$m_size ; ++$i) {
            $key = $arr[$i] . $arr[$i+1] . $arr[$i+2];
            $dict[$key]['offsets'][] = $offset;
            $dict[$key][$arr[$i+3] . $arr[$i+4]][] = $offset;
            $offset += $length[$i] + $length[++$i]; 
        }
    }
     
    build_dict($dict1, $txt1_lc);
    build_dict($dict2, $txt2_lc);
     
    // intersections
    $dict1 = array_intersect_key($dict1, $dict2);
    $dict2 = array_intersect_key($dict2, $dict1);
     
    // traitement
    $results = array();
    $n = 1; // nombre de mots
     
    while($dict1) {
        $n++;
        foreach ($dict1 as $k=>$v) {
            $dict1[$k] = array_intersect_key($dict1[$k], $dict2[$k]);
     
            // on vérifie qu'il y a des mots suivants en commun (aprés intersection)
            if (count($dict1[$k])>1) {
     
                $dict2[$k] = array_intersect_key($dict2[$k], $dict1[$k]); // dans ce cas on réduit également $dict2[$k]
     
                // on récupère et on enlève les anciennes listes d'offsets  
                $offsets1 = array_shift($dict1[$k]);
                $offsets2 = array_shift($dict2[$k]);
     
                foreach ($dict1[$k] as $next_word=>$offsets) {
                    // on créé une nouvelle clef avec l'ancienne et le mot suivant
                    $new_key = $k . $next_word;
                    // on créé la pattern de recherche du mot suivant
                    $pattern = '~' . $new_key . '\K\W++\w+~u';
     
                    // on enlève les offsets qui ont des correspondances plus grandes 
                    $offsets1 = array_diff($offsets1, $offsets);
                    $offsets2 = array_diff($offsets2, $dict2[$k][$next_word]);
     
                    // on créé les listes d'offsets pour les nouvelles clefs 
                    $dict1[$new_key]['offsets'] = $offsets;
                    $dict2[$new_key]['offsets'] = $dict2[$k][$next_word];
     
                    // on cherche le mot suivant pour chaque offset
                    // s'il existe on créé une nouvelle entrée
                    foreach ($offsets as $offset) {
                        if ( preg_match($pattern, $txt1_lc, $m, 0, $offset) )
                            $dict1[$new_key][preg_replace('~\s+~u', '\s+', $m[0])][] = $offset;
                    }
                    foreach ($dict2[$new_key]['offsets'] as $offset) {
                        if ( preg_match($pattern, $txt2_lc, $m, 0, $offset) )
                            $dict2[$new_key][preg_replace('~\s+~u', '\s+', $m[0])][] = $offset;
                    }
                }
                if ($offsets1 && $offset2)
                    $results[$n][$k] = array('1' => $offsets1, '2' => $offsets2);
     
            } else  // il n'y a pas de correspondances de n+1 mots, on stocke les résultats pour n mots.
                $results[$n][$k] = array('1' => $dict1[$k]['offsets'], '2' => $dict2[$k]['offsets']);
     
            unset($dict1[$k], $dict2[$k]);
        }
     
    }
    unset($dict1, $dict2, $txt1_lc, $txt2_lc, $offsets1, $offsets2, $offset, $next_word, $offsets, $new_key, $pattern, $k, $v, $n);
     
    echo "\n\n<strong>results</strong>:\n" . print_r($results, true);
    Dans son état actuel, ce script peut traiter deux fichiers de 100ko en à peu prés 1 seconde, pour 200ko on passe à ~4 secondes, pour 300ko ~10 secondes (ce qui donne une idée de la complexité). Au dela, ce n'est plus seulement un problème de temps mais de mémoire, car la taille des dictionnaires avant les intersections est conséquente. De toute manière, arrivé à une certaine taille, il faut recourir à une base de donnée.

    Pour ce qui est du format du résultat, c'est un tableau contenant les offsets pour chaques correspondances rangées par nombre de mots (on peut facilement modifier le script pour qu'il ait une autre tête).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [PHP 5.3] Comparaison de deux champs de mot de passe
    Par leweb81 dans le forum Langage
    Réponses: 3
    Dernier message: 10/06/2013, 13h44
  2. [WD14] Recherche d'un mot entre deux textes
    Par wojc01 dans le forum WinDev
    Réponses: 6
    Dernier message: 09/11/2009, 19h38
  3. Réponses: 25
    Dernier message: 13/06/2007, 18h09
  4. Comparaison de deux textes
    Par fxparlant dans le forum Langage
    Réponses: 1
    Dernier message: 31/03/2007, 13h54
  5. [HTML] remplissage de ma zone de texte par mot composé?
    Par zorba49 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 07/09/2005, 16h59

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