Jump to content

array_diff() results are wrong


wavez

Recommended Posts

I have two arrays of strings, one is read in from a file, the other is collected on a previous page using js and passed with a form through $_POST. The array from the file I label $oldImages and the array from the previous page I label $newImages (each is a list of image URLs). I need to compare the two and add them together so that there are no duplicate entries. I'm using array_diff() on them and the result I'm getting includes one entry that is in both arrays.

 

I've tried different ways of reading the file, none of them seem to make any difference in the results. I've been printing the arrays with print_r() to have a look at the contents of the arrays and I decided to use implode() and explode(), and str_replace() to try to remove any irregularities that might be in the objects somehow which I'm not seeing. I'm not a PHP programmer, BTW.

 

Here is some code. I've also attached a screenshot for you--link at the bottom.

 

<body>

<?php

$file = file("image_list.txt") or exit("Unable to open file!");

$oldImages = implode($file);
$oldImages = str_replace(" ", "", $oldImages);
$oldImages = explode("\n", $oldImages);


$newImages = implode($_POST);
$newImages = str_replace(" ", "", $newImages);
$newImages = explode("\n", $newImages);

$newAdditions = array_diff($newImages, $oldImages);
print_r($newImages);
echo '<br><br>';
print_r($oldImages);

echo '
<form method="post" action="#">
New Images<br>
<textarea id="displayText" rows="5" cols="105" wrap="off" name="existing">
';
foreach($newImages as $key => $entry) echo $entry;
//echo $newImages;
echo '
</textarea>
<br>

Stored Images<br>
<textarea id="newText" rows="5" cols="105" wrap="off" name="new">
';
foreach($oldImages as $key => $entry) echo $entry;
//echo $oldImages;
echo '
</textarea>
<input type="submit" class="button" value="Submit"><br>
</form>

Newly Generated Image List<br>
<textarea id="newText" rows="30" cols="105" wrap="off" name="new">
';
foreach($newAdditions as $key => $entry) echo $entry;
echo '
</textarea>
';
?>
<div class="clear"></div>


</body>

 

Here is the code from the previous page which produces the array that is stored in $_POST. What you can't see in this code is the javascript functions toggleEntry() and displayList(). All they do is handle the addition and removal of image URL strings to/from the textarea object, which I do using document.getElementById('text').InnerHTML=$myList, where $myList has strings being added or removed to/from it.

 

<script type="text/javascript" src="/js/user_selection_list_builder.js"></script>
<script type="text/javascript">
function toggleAndDisplay(key)
{
toggleEntry(key);
displayList();
}
</script>
</head>


<body>

<form method="post" action="add_images2.php">
Selected Images<br>
<textarea id="displayText" rows="10" cols="90" wrap="off" name="comments">
</textarea>
<input type="submit" class="button" value="Submit">
</form>
<div class="clear"></div>


<?php


$i = 2;

include 'simple_html_dom.php';
if($i===1) $html = file_get_html('lookbook-source.htm');
elseif($i===2) $html = file_get_html('http://lookbook.nu/preference/look-list-gender/girls');
elseif($i===3) $html = file_get_html('http://lookbook.nu/new');



// Match all div tags of the class 'look_photo'.
foreach($html->find('div[class=look_photo]') as $key => $entry)
{
echo "
<div class='imgBox'>
<a href='javascript:toggleAndDisplay(".$key.")'><img id='".$key."' src='".$entry->last_child()->last_child()->src."'></a>
</div>
";
}

?>

</body>

 

a5ycI.jpg

Link to comment
Share on other sites

I changed the code to use trim().

 

<?php

$file = file("image_list.txt") or exit("Unable to open file!");

$oldImages = array();
$newImages = array();

foreach($file as $key => $entry)
{
echo $entry.'<br>';
$oldImages[] = trim($entry);
}

echo '<br>';
foreach($_POST as $key => $entry)
{
echo $entry.'<br>';
$newImages[] = trim($entry);
}

$newAdditions = array_diff($newImages, $oldImages);
$newList = array_merge($oldImages, $newAdditions);
/*
print_r($newImages);
echo '<br><br>';
print_r($oldImages);
*/

echo '
<form method="post" action="save_images_list.php">
New Images<br>
<textarea id="displayText" rows="5" cols="105" wrap="off" name="existing">
';
foreach($newImages as $key => $entry) echo $entry;
//echo $newImages;
echo '
</textarea>
<br>

Stored Images<br>
<textarea id="newText" rows="5" cols="105" wrap="off" name="new">
';
foreach($oldImages as $key => $entry) echo $entry;
//echo $oldImages;
echo '
</textarea><br>

New Additions<br>
<textarea id="newText" rows="10" cols="105" wrap="off" name="new">
';
foreach($newAdditions as $key => $entry) echo $entry;
echo '
</textarea><br>

Newly Generated Image List<br>
<textarea id="newText" rows="30" cols="105" wrap="off" name="new">
';
foreach($newList as $key => $entry) echo $entry;
echo '
</textarea>
<input type="submit" class="button" value="Submit"><br>
</form>
';
?>

 

Looking at the textarea objects, the data from $oldImages is just one big long string, while the data from $newImages is multiple strings. Also, and empty line from the $file input isn't being removed.

 

I'm processing both of these arrays in exactly the same way, yet I'm getting different output. Obviously something is happening with new line characters and who-knows-what other possible invisible characters.

Link to comment
Share on other sites

This is how I'd handle processing the arrays before comparing them.

 

<?php
$oldImages = file("image_list.txt", 6) or exit("Unable to open file!");
if( !empty($oldImages) ) {
$oldImages = array_map('trim', $oldImages);
}

if( strtolower($_SERVER['REQUEST_METHOD']) === 'post' ) {
if( !empty($_POST['newText']) ) {
	$newImages = explode("\n", $_POST['newText']);
	$newImages = array_map('trim', $newImages);
	foreach( $newImages as $k => $v ) {
		if( empty($v) ) {
			unset($newImages[$k]);
		}
	}
}
}

// nothing changed past here . . .
$newAdditions = array_diff($newImages, $oldImages);
$newList = array_merge($oldImages, $newAdditions);

Link to comment
Share on other sites

Ah ha...

 

Sending the contents of the textarea object from the first page stores it all as one item of the $_POST array. I'm going to google it right now, but does anyone know how to have the form automatically breakup the contents of the textarea object into one array entry for each line?

Link to comment
Share on other sites

This is how I'd handle processing the arrays before comparing them.

 

<?php
$oldImages = file("image_list.txt", 6) or exit("Unable to open file!");
if( !empty($oldImages) ) {
$oldImages = array_map('trim', $oldImages);
}

if( strtolower($_SERVER['REQUEST_METHOD']) === 'post' ) {
if( !empty($_POST['newText']) ) {
	$newImages = explode("\n", $_POST['newText']);
	$newImages = array_map('trim', $newImages);
	foreach( $newImages as $k => $v ) {
		if( empty($v) ) {
			unset($newImages[$k]);
		}
	}
}
}

// nothing changed past here . . .
$newAdditions = array_diff($newImages, $oldImages);
$newList = array_merge($oldImages, $newAdditions);

 

That looks like really stellar implementation. I'm trying to use it right now. $oldImages is still coming out as one long string and $newImages is totally empty. I'll try to figure out where it's going wrong.

Link to comment
Share on other sites

I got it working, it seems. I found a couple more issues. For one thing, I didn't know the difference in how PHP handles double-quoted strings and single-quoted strings, which explained why the new-line characters I was trying to insert weren't working. I added code to split the incoming string on every new-line character, then trim the ends, and I needed to add new-line characters back in since my output in the textarea objects was one big long string.

 

Another issue was that I didn't understand how forms work, so the submit button was causing text from ALL my textarea objects to be written to my file on the third page (which I haven't mentioned until now, it's just a page that gets the $_POST variable and writes to the file). To fix it I moved the <form> tag down so that only one textarea object and the submit button are inside it.

 

Other than that, it was just a matter of doing explode("\n",$v); on $_POST['comments] before storing it in $oldImages, and then doing trim($v); on each resulting string. Only when writing the arrays to the textarea objects do I add a new-line character to the end.

 

Thanks for your help Pikachu2000. I'll be sure to choose you in my next battle! :)

 

I can't figure out how to add "[sOLVED]" to the beginning of the thread title.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

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.