Welcome Guest ( Log In | Register)



 
Reply to this topicStart new topic
> Compare Two Vars And Highlight The Differences
Amezis
post Nov 2 2006, 07:08 PM
Post #1


Privileged Member
*********

Group: Members
Posts: 535
Joined: 14-February 05
From: Oslo, Norway
Member No.: 3,759



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:

IPB 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.
Go to the top of the page
 
+Quote Post
hts
post Nov 2 2006, 08:01 PM
Post #2


Advanced Member
*******

Group: Members
Posts: 138
Joined: 30-September 06
From: Iasi, Romania
Member No.: 30,851



CODE

$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 wink.gif )
Go to the top of the page
 
+Quote Post
Amezis
post Nov 3 2006, 08:26 AM
Post #3


Privileged Member
*********

Group: Members
Posts: 535
Joined: 14-February 05
From: Oslo, Norway
Member No.: 3,759



Well, I've never used foreach. And there is an error with your code. I entered these vars:
CODE
$string1 = "test first and test again";
$string2 = "test second and test again";


And this is what it returns:
CODE
<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:
CODE
$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.
Go to the top of the page
 
+Quote Post
hts
post Nov 3 2006, 01:56 PM
Post #4


Advanced Member
*******

Group: Members
Posts: 138
Joined: 30-September 06
From: Iasi, Romania
Member No.: 30,851



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 tongue.gif...maybe I`ll come up with something better...
Go to the top of the page
 
+Quote Post
jlhaslip
post Nov 3 2006, 04:51 PM
Post #5


A computer once beat me at chess, but it was no match for me at kick boxing.
Group Icon

Group: [MODERATOR]
Posts: 4,083
Joined: 24-July 05
From: Linix, DOS and Windows…the good, the bad and the ugly
Member No.: 9,787
Spam Patrol



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.
Go to the top of the page
 
+Quote Post
electron
post Nov 6 2006, 04:56 AM
Post #6


Premium Member
********

Group: Members
Posts: 162
Joined: 10-May 06
Member No.: 23,375



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.

QUOTE
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().

CODE
<?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:

CODE
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.
Go to the top of the page
 
+Quote Post
truefusion
post Nov 6 2006, 12:54 PM
Post #7


Ephesians 6:10-17
Group Icon

Group: [MODERATOR]
Posts: 1,918
Joined: 22-June 05
From: The World of Gentoo
Member No.: 8,528



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:
CODE
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:
CODE
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 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);
}
}


To output it use this:
CODE
$output = compare_contrast($str1, $str2);
echo $output[0];
echo $output[1];
Go to the top of the page
 
+Quote Post
Amezis
post Jan 18 2007, 06:30 PM
Post #8


Privileged Member
*********

Group: Members
Posts: 535
Joined: 14-February 05
From: Oslo, Norway
Member No.: 3,759



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:
CODE
$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?

This post has been edited by Amezis: Jan 18 2007, 06:32 PM
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic