0 Replies Latest reply on Nov 17, 2009 12:49 AM by ab1301

    Flex Diff Algorithm

    ab1301

      A guy named Paul Butler made a diff algorithm for PHP.  It compares two strings, and shows you the differences between the strings.  The original PHP code is here:

       

      http://github.com/paulgb/simplediff/blob/5bfe1d2a8f967c7901ace50f04ac2d9308ed3169/simpledi ff.php

       

      I have translated it into Flex, and given it an Air wrapper  (the two primary functions, diff and HTMLdiff should work fine in any flex app, but the wrapper requires AIR since it uses an HTML container).  Just putting this out there, as it is kind of cool and may be useful to some folks.  The code is pretty ugly, so if anyone wants to clean it up, please do so and repost (the comments were meant to help me translate from PHP to actionscript):

       

      <?xml version="1.0" encoding="utf-8"?>
      <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" height="300" width="400" viewSourceURL="srcview/index.html">
          <mx:Label x="10" y="10" text="Old:"/>
          <mx:TextArea x="10" y="36" width="194" height="110" id="oldbox" text="This is the original text before any changes have been made."/>
          <mx:Label x="212" y="10" text="New:"/>
          <mx:TextArea x="212" y="36" width="176" height="110" id="newbox" text="This is the new text after all the changes were made."/>
          <mx:HTML right="10" left="10" top="180" bottom="10" id="result"/>
          <mx:Button x="347" y="8" label="Go" click="go()"/>
          <mx:Script>
              <![CDATA[
             
                  public function diff($old:Array, $new:Array):Array{
                      var $matrix:Array = new Array();
                      var $maxlen:uint;
                      var $omax:uint;
                      var $nmax:uint;
                      var $return:Array = new Array();
                      var $subreturn:Array = new Array();
                      //The next two lines imitate foreach($old as $oindex => $ovalue){
                      for (var $oindexstring:String in $old){
                          var $oindex:uint = uint($oindexstring);
                          var $ovalue:String = $old[$oindex];
                      //The next lines imitate $nkeys = array_keys($new, $ovalue);   
                          var $nkeys:Array = new Array();
                          for (var $nkey:String in $new){
                              if ($new[$nkey] == $ovalue){
                                  $nkeys.push($nkey);
                              }
                          }
                      //The next line imitates foreach($nkeys as $nindex){
                          for each (var $nindex:uint in $nkeys){
                              //The next line imitates $matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex -1]) ? $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
                              if ($matrix.hasOwnProperty(String($oindex-1))){
                                  if ($matrix[$oindex-1].hasOwnProperty(String($nindex-1))){
                                      if ($matrix.hasOwnProperty(String($oindex))){
                                          $matrix[$oindex][$nindex] = $matrix[$oindex - 1][$nindex - 1] + 1;
                                      } else {
                                          $matrix[$oindex] = new Array();
                                          $matrix[$oindex][$nindex] = $matrix[$oindex - 1][$nindex - 1] + 1;
                                      }
                                  } else {
                                      if ($matrix.hasOwnProperty(String($oindex))){
                                          $matrix[$oindex][$nindex] = 1;
                                      } else {
                                          $matrix[$oindex] = new Array();
                                          $matrix[$oindex][$nindex] = 1;
                                      }
                                  }
                              } else {
                                  if ($matrix.hasOwnProperty(String($oindex))){
                                      $matrix[$oindex][$nindex] = 1;
                                  } else {
                                      $matrix[$oindex] = new Array();
                                      $matrix[$oindex][$nindex] = 1;
                                  }
                              }
                              if ($matrix[$oindex][$nindex] > $maxlen){
                                  $maxlen = $matrix[$oindex][$nindex];
                                  $omax = $oindex + 1 - $maxlen;
                                  $nmax = $nindex + 1 - $maxlen;
                              }
                          }
                      }
                      if($maxlen == 0){
                          $subreturn["d"] = $old;
                          $subreturn["i"] = $new;
                          $return.push($subreturn);
                          return $return;
                      } else {
                          //Next line is diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax));
                          $subreturn = diff($old.slice(0, $omax), $new.slice(0, $nmax));
                          $return = $return.concat($subreturn);
                          //Next line imitates array_slice($new, $nmax, $maxlen)
                          $subreturn = $new.slice($nmax, $nmax + $maxlen);
                          $return = $return.concat($subreturn);
                          //Next line is diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen))
                          $subreturn = diff($old.slice($omax + $maxlen), $new.slice($nmax + $maxlen));
                          $return = $return.concat($subreturn);
                          return $return;
                      }
                  }
                 
                  public function go():void{
                      result.htmlText = htmlDiff(oldbox.text, newbox.text);
                  }
             
                  public function htmlDiff($old:String, $new:String):String{
                      var $ret:String = "";
                      var $diff:Array = diff($old.split(" "), $new.split(" "));
                      for each(var $k:Object in $diff){
                          if($k.constructor == Array){
                              //$ret += (!empty($k['d'])?"<del>".implode(' ',$k['d'])."</del> ":'').
                              if ($k['d'] == undefined || $k['d'].length == 0){
                                  $ret += "";
                              } else {
                                  $ret += "<del style=\"color: red ; text-decoration: line-through\" >"+$k["d"].join(" ")+"</del> ";
                              }
                              //(!empty($k['i'])?"<ins>".implode(' ',$k['i'])."</ins> ":'');
                              if ($k['i'] == undefined || $k['i'].length == 0){
                                  $ret += "";
                              } else {
                                  $ret += "<ins style=\"color: blue ; text-decoration: underline\" >"+$k["i"].join(" ")+"</ins> "
                              }
                          } else {
                              $ret += $k + ' ';
                          }
                      }
                      return "<html><body>"+$ret+"</body></html>";
                  }
              ]]>
          </mx:Script>
          <mx:Label x="10" y="154" text="Diff Result:"/>
      </mx:WindowedApplication>