Jump to content
xisto Community
Amezis

Compare Two Vars And Highlight The Differences

Recommended Posts

I need a script that compares 2 variables, and looks for a difference between them. It will then highlight the words that are different, as shown in the image below:

 

Posted Image

 

So in the left cell, the yellow text is the text that has been removed OR replaced.

 

In the right cell, the green text is the text that has replaced some text in the left cell, OR new text.

 

 

This script will be used to compare 2 versions of a document stored in the database, to see the difference between each change (all revisions are stored in the database). I know that it's possible with PHP, because Wikipedia, which is coded in PHP, uses it, but I have absolutely no clue on how to do it. Any suggestions?

 

Note: This was originally posted back here, but that topic seems dead, so I decided to make a new topic.

Share this post


Link to post
Share on other sites
$string1 = "This is my first sentence";$string2 = "This is my second sentence";$find = explode(" ",$string1);foreach($find as $word){$text = str_replace ($word, "<b>$word</b>", $string2);$string2=$text;}echo $text;

this might be a starting point for you..it has flaws, as you will notice when you`ll run it ..also, it doesn't do exactly what you`ve asked for..well, just try it for yourself and maybe you`ll be able to modify it to fit your needs (ps: differences are bolded :lol: )

Share this post


Link to post
Share on other sites

Well, I've never used foreach. And there is an error with your code. I entered these vars:

$string1 = "test first and test again";$string2 = "test second and test again";

And this is what it returns:
<b><b>test</b></b> second <b>and</b> <b><b>test</b></b> <b>again</b>

On the words "test", there are two <b> tags, because the word "test" appears twice, and it actually highlights the words that are the same, not the words that are different.

And there was another bug:
$string1 = "a variable is here";$string2 = "a variable is there";// Output:<b>a</b> v<b>a</b>ri<b>a</b>ble <b>is</b> t<b>here</b>
So "a" is highlighted inside the word "variable" too.

Share this post


Link to post
Share on other sites

well yes, I knew about those errors..I`ve tested this script on my local server and the "a" letter was highlighted inside a word, too..sorry for this..I`ll think on this, as I might need it sometime later :lol:...maybe I`ll come up with something better...

Share this post


Link to post
Share on other sites

After you explode the string, before you add the bold tags, make the array contain only unique entries.
I think the function is called array_unique().
Look on the php.net site for confirmation of the function and the details.

Share this post


Link to post
Share on other sites

Well after exploding the same why dont you guys use the array_diff_assoc() function or the array_diff() function.
array_diff_assoc() function would be more appropriate though.

array_diff_assoc() returns an array containing all the values from array1 that are not present in any of the other arguments. Note that the keys are used in the comparison unlike array_diff().

<?php$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");$array2 = array("a" => "green", "yellow", "red");$result = array_diff_assoc($array1, $array2);print_r($result);?>

The above example will output:

Array(   [b] => brown   [c] => blue   [0] => red)

Well hope this will help in atleast finding the difference.
But how will you arrange the thing I have not come up with that as yet.

Share this post


Link to post
Share on other sites

After hours of trial and error, i've managed to make a function that does almost exactly what you want! However, there's one tiny little bug i have to fix, before i release it. It seems to be duplicating the last word...

 

EDIT:


$split1 = preg_split('/\s/', $var1);

 

//

 

$offset2 = preg_split('/\s/', $var2, -1, PREG_SPLIT_OFFSET_CAPTURE);

$split2 = preg_split('/\s/', $var2);

 

//

 

$diff1 = array_diff_assoc($split1, $split2);

 

$i = 0;

 

foreach ($diff1 as $key => $value){

if ($i == 0){

$compare = substr_compare($var1, $offset1[$key][0], $offset1[$key][1], strlen($var1));

$compare = intval("-$compare");

$temp1 = substr_replace($var1, "<b>".$offset1[$key][0]."</b>", $offset1[$key][1], $compare);

 

$i = $i + 7;

}

else {

$compare = (strlen($var1)+$i) - (($offset1[$key][1]+$i) + strlen($offset1[$key][0]));

$compare = intval("-$compare");

if ($compare < 0){

$temp1 = substr_replace($temp1, "<b>".$offset1[$key][0]."</b>", $offset1[$key][1]+$i, $compare);

}

else {

$temp1 = substr_replace($temp1, "<b>".$offset1[$key][0]."</b>", $offset1[$key][1]+$i);

}

 

$i = $i + 7;

}

}

 

//

 

$diff2 = array_diff_assoc($split2, $split1);

 

$i = 0;

 

foreach ($diff2 as $key => $value){

if ($i == 0){

$compare = substr_compare($var2, $offset2[$key][0], $offset2[$key][1], strlen($var2));

$compare = intval("-$compare");

$temp2 = substr_replace($var2, "<b>".$offset2[$key][0]."</b>", $offset2[$key][1], $compare);

 

$i = $i + 7;

}

else {

$compare = (strlen($var2)+$i) - (($offset2[$key][1]+$i) + strlen($offset2[$key][0]));

$compare = intval("-$compare");

if ($compare < 0){

$temp2 = substr_replace($temp2, "<b>".$offset2[$key][0]."</b>", $offset2[$key][1]+$i, $compare);

}

else {

$temp2 = substr_replace($temp2, "<b>".$offset2[$key][0]."</b>", $offset2[$key][1]+$i);

}

 

$i = $i + 7;

}

}

 

$output = array($temp1, $temp2);

return $output;

} linenums:0'>function compare_contrast($var1, $var2){$offset1 = preg_split('/\s/', $var1, -1, PREG_SPLIT_OFFSET_CAPTURE);$split1 = preg_split('/\s/', $var1);//$offset2 = preg_split('/\s/', $var2, -1, PREG_SPLIT_OFFSET_CAPTURE);$split2 = preg_split('/\s/', $var2);//$diff1 = array_diff_assoc($split1, $split2);$i = 0;foreach ($diff1 as $key => $value){if ($i == 0){$compare = substr_compare($var1, $offset1[$key][0], $offset1[$key][1], strlen($var1));$compare = intval("-$compare");$temp1 = substr_replace($var1, "<b>".$offset1[$key][0]."</b>", $offset1[$key][1], $compare);$i = $i + 7;}else {$compare = (strlen($var1)+$i) - (($offset1[$key][1]+$i) + strlen($offset1[$key][0]));$compare = intval("-$compare");if ($compare < 0){$temp1 = substr_replace($temp1, "<b>".$offset1[$key][0]."</b>", $offset1[$key][1]+$i, $compare);}else {$temp1 = substr_replace($temp1, "<b>".$offset1[$key][0]."</b>", $offset1[$key][1]+$i);}$i = $i + 7;}}//$diff2 = array_diff_assoc($split2, $split1);$i = 0;foreach ($diff2 as $key => $value){if ($i == 0){$compare = substr_compare($var2, $offset2[$key][0], $offset2[$key][1], strlen($var2));$compare = intval("-$compare");$temp2 = substr_replace($var2, "<b>".$offset2[$key][0]."</b>", $offset2[$key][1], $compare);$i = $i + 7;}else {$compare = (strlen($var2)+$i) - (($offset2[$key][1]+$i) + strlen($offset2[$key][0]));$compare = intval("-$compare");if ($compare < 0){$temp2 = substr_replace($temp2, "<b>".$offset2[$key][0]."</b>", $offset2[$key][1]+$i, $compare);}else {$temp2 = substr_replace($temp2, "<b>".$offset2[$key][0]."</b>", $offset2[$key][1]+$i);}$i = $i + 7;}}$output = array($temp1, $temp2);return $output;}

This is the best i could get it as.

 

If you're using PHP 4, then you'll need this as well:


function substr_compare($main_str, $str, $offset, $length = NULL, $case_insensitivity = false){

$offset = (int) $offset;

 

// Throw a warning because the offset is invalid

if ($offset >= strlen($main_str)){

trigger_error('The start position cannot exceed initial string length.', E_USER_WARNING);

return false;

}

 

// We are comparing the first n-characters of each string, so let's use the PHP function to do it

if ($offset == 0 && is_int($length) && $case_insensitivity === true){

return strncasecmp($main_str, $str, $length);

}

 

// Get the substring that we are comparing

if (is_int($length)){

$main_substr = substr($main_str, $offset, $length);

$str_substr = substr($str, 0, $length);

} else {

$main_substr = substr($main_str, $offset);

$str_substr = $str;

}

 

// Return a case-insensitive comparison of the two strings

if ($case_insensitivity === true){

return strcasecmp($main_substr, $str_substr);

}

 

// Return a case-sensitive comparison of the two strings

return strcmp($main_substr, $str_substr);

}

} linenums:0'>if (!function_exists('substr_compare')){function substr_compare($main_str, $str, $offset, $length = NULL, $case_insensitivity = false){$offset = (int) $offset;// Throw a warning because the offset is invalidif ($offset >= strlen($main_str)){trigger_error('The start position cannot exceed initial string length.', E_USER_WARNING);return false;}// We are comparing the first n-characters of each string, so let's use the PHP function to do itif ($offset == 0 && is_int($length) && $case_insensitivity === true){return strncasecmp($main_str, $str, $length);}// Get the substring that we are comparingif (is_int($length)){$main_substr = substr($main_str, $offset, $length);$str_substr = substr($str, 0, $length);} else {$main_substr = substr($main_str, $offset);$str_substr = $str;}// Return a case-insensitive comparison of the two stringsif ($case_insensitivity === true){return strcasecmp($main_substr, $str_substr);}// Return a case-sensitive comparison of the two stringsreturn strcmp($main_substr, $str_substr);}}


To output it use this:
$output = compare_contrast($str1, $str2);echo $output[0];echo $output[1];

Share this post


Link to post
Share on other sites

Thanks a lot Truefusion, but there is still one bug: If a word has been added, it will highlight everything after the word. So the script wouldn't work correctly with this:

$var1 = 'A web site with information and stuff';$var2 = 'A web page with nice information and stuff';

page/site will be highlighted correctly, but I added the word "nice" in the second variable, so everything after that word has been highlighted. Any idea on how to fix that?
Edited by Amezis (see edit history)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.