Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Jul 2007
    Messaggi
    15

    Differenze tra due stringhe

    Buongiorno a tutti,
    ho un quesito da porre a tutti voi, nella speranza di ottenere almeno un indicazione su come operare, perchè sono assolutamente immerso nella nebbia. :master:

    ho 2 stringhe di testo, che il più delle volte, ma non è la regola, differiscono di poche parole. L'obiettivo sarebbe individuare , ed indicare, le differenze tra le due stringhe.

    Una prima soluzione potrebbe fermarsi a stringhe differenti per pochi caratteri, ma il risultato conclusivo a cui vorrei arrivare è un analisi approfondita in grado di scoprire, ed indicare, anche grosse modifiche nel testo.

    Qualcuno può suggerirmi qualche soluzione?

    Ringrazio per l'attenzione.
    Andrea

  2. #2
    Puoi implementare l'algoritmo Longest Common Subsequence. Su Wikipedia trovi anche dello pseudo codice di facile comprensione:

    http://en.wikipedia.org/wiki/Longest...quence_problem

  3. #3
    Utente di HTML.it
    Registrato dal
    Jul 2007
    Messaggi
    15
    grazie mille. studio un po' questo codice.

  4. #4
    Utente di HTML.it
    Registrato dal
    Jul 2007
    Messaggi
    15
    Rieccomi. Ho sviluppato la funzione per la ricerca delle differenze tra due testi.
    Di seguito posto il codice.

    Codice PHP:
    /*LA FUNZIONE RESTITUISCE IL TESTO SOTTOLINEANDO LE DIFFERENZE */
    function cambiato($testo,$old_tac){
       
    //$stringa1 = "Andrea guida la vespa fino a casa e la macchina fino a dicembre";
       //$stringa2 = "Andrea guida la vespa sgommando e lascia la macchina fino a gennaio";
       
    $stringa2 stripslashes($testo);
       
    $stringa1 stripslashes($old_tac);
       
    $return=''//$return è la stringa che ritorneremo
       //$return.= $stringa1."
    ";

       
    $array1=explode(' ',$stringa1); //dividiamo le due stringhe parola per parola
       
    $array2=explode(' ',$stringa2);

       if (count(
    $array1)>count($array2)) //ricerchiamo la stringa di lunghezza massima
          
    $massimo=count($array1);
       else
          
    $massimo=count($array2);
       
    $j=0;

       for (
    $i=0; $i<$massimo$i++){ //scandiamo parola per parola e facciamo i vari confronti
          
    $k=1;
          
    $cicla=true;
          if (strcmp(
    $array1[$i],$array2[$j])==0){ //le due parole sono uguali, non c'è stata modifica. stampiamo la parola e passiamo alla successiva
             
    $j++;
             
    $return.= $array1[$i]." ";
          }else{ //le due parole sono diverse
             while(
    $cicla){
                
    $stringa='';
                
    $stringa_2='';
                /* CONTROLLO TESTO AGGIUNTO */
                if (strcmp(
    $array1[$i],$array2[$j+$k])==0){ //controlliamo se la parola del testo vecchio è uguale ad una parola k spazi + avanti del testo nuovo, in tal caso nel nuovo testo sono state aggiunte k parole.

                   for (
    $n=0;$n<$k;$n++){
                      if (
    $n<$k-1)
                         
    $stringa.=$array2[$j+$n]." "; //stampiamo in verde e grassetto le parole aggiunte
                      else
                         
    $stringa.=$array2[$j+$n];
                  }
                  
    $return.= '<font color="green">[b]'.$stringa.'[/b]</font> '.$array1[$i].' ';
                  
    $cicla=false;
                  
    $j=$j+$k+1;
              }else{
              /* CONTROLLO TESTO ELIMINATO */
                 if(strcmp(
    $array1[$i+$k],$array2[$j])==0){ //controlliamo se la parola del testo nuovo è uguale ad una parola k spazi + avanti del testo vecchio, in tal caso nel nuovo testo sono state eliminate k parole.

                   for (
    $n=0;$n<$k;$n++){
                      if (
    $n<$k-1)
                         
    $stringa.=$array1[$i+$n]." "; //stampiamo barrato e in rosso la porzione di testo vecchio eliminata nel testo nuovo
                      else
                         
    $stringa.=$array1[$i+$n];
                   } 
                   
    $cicla=false;
                   
    $return.= '<font color="red"><strike>'.$stringa.'</strike></font> '.$array2[$j].' ';
                   
    $j=$j+1;
                   
    $i=$i+$k;
                }else{

                   for (
    $n=1;$n<=$k;$n++){
                   /* CONTROLLO SCAMBIO TESTO */
                      if(strcmp(
    $array1[$i+$k],$array2[$j+$n])==0){ //controlliamo se una parola compresa tra 1 e k-1 passi del testo nuovo è uguale alla parola k passi + avanti del testo vecchio
                         for (
    $r=0;$r<$k;$r++){
                            if (
    $r<$k-1)
                               
    $stringa.=$array1[$i+$r]." ";
                            else
                               
    $stringa.=$array1[$i+$r];
                         }
                         for (
    $r=0;$r<$n;$r++){ //stampiamo le parole del testo vecchio che sono state sostituite in rosso barrato e in verde grassetto quelle che sono state aggiunte al loro posto
                         if (
    $r<$n-1)
                            
    $stringa_2.=$array2[$j+$r]." ";
                         else
                            
    $stringa_2.=$array2[$j+$r];
                         }
                         
    $return.= '<font color="red"><strike>'.$stringa.'</strike></font> <font color="green">[b]'.$stringa_2.'[/b]</font> '.$array1[$i+$k].' ';
                         
    $cicla=false;
                         
    $i=$i+$k;
                         
    $j=$j+$n+1;
                         
    $n=$k;
                      }else{
                         /* CONTROLLO SCAMBIO TESTO */
                         if(strcmp(
    $array1[$i+$n],$array2[$j+$k])==0){ //controlliamo se una parola compresa tra 1 e k-1 passi del testo vecchio è uguale alla parola k passi + avanti del testo nuovo
                            for (
    $r=0;$r<$n;$r++){
                               if (
    $r<$n-1)
                                  
    $stringa.=$array1[$i+$r]." ";
                               else
                                  
    $stringa.=$array1[$i+$r];
                            }
                            for (
    $r=0;$r<$k;$r++){
                               if(
    $r<$k-1)
                                  
    $stringa_2.=$array2[$j+$r]." "; //stampiamo le parole del testo vecchio che sono state sostituite in rosso barrato e in verde grassetto quelle che sono state aggiunte al loro posto
                               else
                                  
    $stringa_2.=$array2[$j+$r];
                            }
                            
    $return.= '<font color="red"><strike>'.$stringa.'</strike></font> <font color="green">[b]'.$stringa_2.'[/b]</font> '.$array1[$i+$n].' ';
                            
    $cicla=false;
                            
    $i=$i+$n;
                            
    $j=$j+$k+1;
                            
    $n=$k;
                          }
                       }
                    }
                 }
              }
              
    $k++; //incrementiamo il numero di passi da controllare
           }
         }
      }
      return 
    $return; //restituiamo la stringa di testo nuovo con evidenziate le modifiche

    Innanzi tutto chiedo scusa per la lunghezza.
    Spiego brevemente il funzionamento:
    - divido le stringhe ad ogni spazio, quindi vengono inserite le parole in un array.
    - scandisco parola per parola.
    - se le parole sono uguali, la stampo
    - se le parole sono diverse inizia la ricerca delle differenze, sfruttando diversi indici. (lascio lo studio del codice per capire il funzionamento esatto).
    - trovate le differenze stampa in rosso barrato il testo eliminato e in verde grassetto il testo aggiunto.

    C'è un problema, immagino anche il motivo, ma chiedo conferma. Ho notato che per testi molto lunghi, la funzione dopo un po' impazzisce. Si perde. Insomma indica come differenti testi uguali, cancellando e riscrivendo le stesse cose.

    Quindi chiedo:
    il motivo può essere un qualche limite nella dimensione dell'array? E quanto vale questo limite? c'è un modo per superarlo?

    Ringrazio per l'attenzione,
    Andrea

  5. #5
    - divido le stringhe ad ogni spazio, quindi vengono inserite le parole in un array.
    E' meglio se utilizzi:

    Codice PHP:
    $array preg_split('#\\s+#si'$stringa); 
    E' piu' flessibile come soluzione.

  6. #6
    Ottimo il codice di Tro4, è proprio quello che mi serviva.
    Non ti funzionava perché mancavano un paio di if qua e là.
    Mi sono permesso di correggerlo e, almeno per quello che mi serve, ora funziona egregiamente e senza errori né warning:

    Codice PHP:
    /*LA FUNZIONE RESTITUISCE IL TESTO SOTTOLINEANDO LE DIFFERENZE */
    function cambiato($testo$old_tac)
    {
       
    $stringa1 stripslashes($testo);
       
    $stringa2 stripslashes($old_tac);

       
    $return ''

        
    $thelf chr(10);
        
    $thecr chr(13);    
        
    $thecrlf = array ($thecr.$thelf$thelf.$thecr$thecr$thelf);
        
        
    // faccio questo per preservare gli accapo
        
    $stringa1 str_replace($thecrlf'{NL}'$stringa1);
        
    $stringa2 str_replace($thecrlf'{NL}'$stringa2);

        
    $array1 preg_split('#\s+#si'$stringa1);
        
    $array2 preg_split('#\s+#si'$stringa2);

        
    // ricerchiamo la stringa di lunghezza massima
        
    $count_array1 count($array1);
        
    $count_array2 count($array2);
         
           
    $massimo max ($count_array1$count_array2);
       
           
    $j 0;
       
        
    // scandiamo parola per parola e facciamo i vari confronti
       
    for ($i 0$i $massimo$i++)
       {
             
    //if (($i >= $count_array1) || ($i >= $count_array2)) break;
          //if (($j >= $count_array1) || ($j >= $count_array2)) break;
            
          
    if (($i >= $count_array1) || ($j >= $count_array2)) break;
            
          
    $k 1;
          
    $cicla true;
          
           
    // le due parole sono uguali, non c'è stata modifica. stampiamo la parola e passiamo alla successiva
          
    if ($array1[$i] == $array2[$j])
          {
             
    $j++;
             
    $return .= $array1[$i]." ";
          }
          else 
    // le due parole sono diverse
          
    {
             while (
    $cicla)
             {
                 
    //if ($i >= $count_array1) break;
                //if ($j >= $count_array2) break;
                //if (($i + $k) >= $count_array1) break;
                //if (($j + $k) >= $count_array2) break;
                
                
    $stringa '';
                
    $stringa_2 '';
                
                
    /* CONTROLLO TESTO AGGIUNTO */
                
    if ($array1 [$i] == $array2 [$j $k])
                { 
                    
    // controlliamo se la parola del testo vecchio è uguale ad una parola k spazi + avanti 
                    // del testo nuovo, in tal caso nel nuovo testo sono state aggiunte k parole.

                       
    for ($n 0$n $k$n++)
                    {
                        
    // stampiamo in verde e grassetto le parole aggiunte
                          
    if ($n < ($k 1)) $stringa .= $array2 [$j $n] . " "
                          else 
    $stringa .= $array2 [$j $n];
                      }
                    
                      
    $return .= '<font color="green">[b]'.$stringa.'[/b]</font> '.$array1[$i].' ';
                      
    $cicla false;
                  
                      
    $j $j $k 1;
                  }
                  else
                  {
                      
    /* CONTROLLO TESTO ELIMINATO */
                     
    if ($array1 [$i $k] == $array2 [$j])
                     { 
                        
    // controlliamo se la parola del testo nuovo è uguale ad una parola k 
                        // spazi + avanti del testo vecchio, in tal caso nel nuovo testo sono state eliminate k parole.
                           
    for ($n 0$n $k$n++)
                           {
                            
    // stampiamo barrato e in rosso la porzione di testo vecchio eliminata nel testo nuovo
                              
    if ($n < ($k 1)) $stringa .= $array1 [$i $n]." ";                         
                              else 
    $stringa .= $array1 [$i $n];
                           }
                   
                           
    $cicla false;
                           
    $return .= '<font color="red"><strike>'.$stringa.'</strike></font> '.$array2[$j].' ';
                           
    $j $j 1;
                           
    $i $i $k;
                    }
                    else
                    {
                           for (
    $n 1$n <= $k$n++)
                           {
                               
    /* CONTROLLO SCAMBIO TESTO */
                              
    if ($array1 [$i $k] == $array2 [$j $n])
                              { 
                                
    // controlliamo se una parola compresa tra 1 e k-1 passi del testo nuovo 
                                // è uguale alla parola k passi + avanti del testo vecchio
                                 
    for ($r 0$r $k$r++)
                                 {
                                    if (
    $r < ($k 1)) $stringa .= $array1 [$i $r]." ";
                                    else 
    $stringa .= $array1 [$i $r];
                                 }
                         
                                 for (
    $r 0$r $n$r++)
                                 { 
                                    
    // stampiamo le parole del testo vecchio che sono state sostituite in rosso 
                                    // barrato e in verde grassetto quelle che sono state aggiunte al loro posto
                                     
    if ($r < ($n 1)) $stringa_2 .= $array2 [$j $r]." ";
                                     else 
    $stringa_2 .= $array2 [$j $r];
                                 }
                         
                                 
    $return .= '<font color="red"><strike>'.$stringa.'</strike></font> <font color="green">[b]'.$stringa_2.'[/b]</font> '.$array1[$i+$k].' ';
                                
                                 
    $cicla false;
                                 
    $i $i $k;
                                 
    $j $j $n 1;
                                 
    $n $k;
                              }
                              else
                              {
                                 
    /* CONTROLLO SCAMBIO TESTO */
                                 
    if ($array1 [$i $n] == $array2 [$j $k])
                                 { 
                                    
    // controlliamo se una parola compresa tra 1 e k-1 passi del testo vecchio è 
                                    // uguale alla parola k passi + avanti del testo nuovo
                                    
    for ($r 0$r $n$r++)
                                    {
                                           if (
    $r < ($n 1)) $stringa .= $array1 [$i $r]." ";
                                           else 
    $stringa .= $array1 [$i $r];
                                    }
                            
                                    for (
    $r 0$r $k$r++)
                                    {
                                           if (
    $r < ($k 1)) $stringa_2 .= $array2 [$j $r]." "
                                        
                                        
    // stampiamo le parole del testo vecchio che sono state sostituite in rosso
                                        // barrato e in verde grassetto quelle che sono state aggiunte al loro posto
                                           
    else $stringa_2 .= $array2 [$j $r];
                                    }
                            
                                    
    $return .= '<font color="red"><strike>'.$stringa.'</strike></font> <font color="green">[b]'.$stringa_2.'[/b]</font> '.$array1[$i+$n].' ';
                                    
                                    
    $cicla false;
                                    
    $i $i $n;
                                    
    $j $j $k 1;
                                    
    $n $k;
                                  }
                               }
                        }
                     }
                  }
              
                  
    $k++; //incrementiamo il numero di passi da controllare
               
    }
         }
      }

        if (!empty (
    $return))
        {
            
    // rimetto gli accapo (solo il LF, che poi sostituirò con 
    )
            
    $return str_replace('{NL}'$thelf$return);
        }
        
          return 
    $return//restituiamo la stringa di testo nuovo con evidenziate le modifiche

    Vi prego di aggiornare questo post nel caso ci sia qualcuno che migliora questa funzione con nuove funzionalità, ok?

    Ciao a tutti!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.