[SOLVED] How to find if two multidimensional arrays match

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

[SOLVED] How to find if two multidimensional arrays match

Post by Stryks »

Hi all,

I have two mutidimensional arrays holding information about assorted products and upgrades.

This first is the prepared information of a new item to be added, and the second is a list of items in the cart. I want to loop through the second array and compare it to the first, returning a true or false answer to if they match.

The objective is that if an item to be added to the cart matches one already there, it will just increase the count instead of adding a second identical item.

I'm sure I could tack together some obscure code to do it but I thought I 'd check to see if anyone had any ideas to help get it done a bit better.

Thanks
Last edited by Stryks on Thu Sep 28, 2006 7:03 am, edited 1 time in total.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

array_walk() or array_diff() could be useful possibly.
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Post by Stryks »

Yeah, I've been looking at array_diff(), but mainly I'm concerned with how messy I'm going to make it when I try and use it recursively.

I'll take a closer look at array_walk() but I never seem to be able to get it to do exactly what I want. Of course, I've never used it to try and do this so this may be what it is good for.

Thanks
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Post by Stryks »

See, this is my constant fear .... I'm always going to come up with the most boring way to do it ....

Code: Select all

<?php 
$sweet = array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => 'lemon');
$sweet = array('a' => 'apples', 'b' => 'banana');
$vegies = array('sweet' => $sweet, 'sour' => 'lemon');

function arr_identical($test_arr_1, $test_arr_2) {
	if(is_array($test_arr_1)) {
		foreach($test_arr_1 as $id_1=>$value_1) {
			if(isset($test_arr_2[$id_1])) {
				if(is_array($value_1)) {
					if(!arr_identical($value_1, $test_arr_2[$id_1])) return false;
				} else {
					if(!($value_1 === $test_arr_2[$id_1])) return false;
				}
			} else return false;
		}		
	}
	return true;
}

if(arr_identical($fruits, $vegies)) echo "They Matched"; else echo "They Didnt Match";

?>
It works I guess .... but can anyone give me a cleaner / faster method?
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Post by Stryks »

Actually, that didn't really work that well after all. If the second array had values that the first one didnt but otherwise matched, it returned true.

This fixes it:

Code: Select all

$sweet = array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => 'lemon');
$sweet = array('a' => 'apple', 'b' => 'banana');
$vegies = array('sweet' => $sweet, 'sour' => 'lemon', 'bitter' => 'vinegar');

function arr_identical($test_arr_1, $test_arr_2) {
	if((is_array($test_arr_1)) && (is_array($test_arr_2))) {
		if(count($test_arr_1) == count($test_arr_2)) {
			foreach($test_arr_1 as $id_1=>$value_1) {
				if(isset($test_arr_2[$id_1])) {
					if(is_array($value_1)) {
						if(!arr_identical($value_1, $test_arr_2[$id_1])) return false;
					} else {
						if(!($value_1 === $test_arr_2[$id_1])) return false;
					}
				} else return false;
			}		
		} else return false;
	} else return false;
	return true;
}

if(arr_identical($fruits, $vegies)) echo "They Matched"; else echo "They Didnt Match";
Still .... I feel like I'm tackling this the wrong way. I've tried to use the functions mentioned earlier, but I dont know .... I cant seem to wrangle a solution out of it.

If anyone can offer a cleaner alternative, it'd be greatly appreciated.
mickd
Forum Contributor
Posts: 397
Joined: Tue Jun 21, 2005 9:05 am
Location: Australia

Post by mickd »

Since i've never used array_diff before i'm just assuming that something like this should work.

Code: Select all

<?php

function array_identical($array_1, $array_2) {

if(empty(array_diff($array_1, $array_2)) && empty(array_diff($array_2, $array_1)) {

return true;

} else {

return false;

}

}

?>
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

I really see this as a problem with the coding prior to this point. If all your items have a unique id use this as you array key. Example:

Code: Select all

<?php

$items = array('dog' => 'dog', 'dogfood' => 'dogfood');
$cart = array();

# buy a dog
@$cart[$items['dog']]++;

#buy dog food
@$cart[$items['dogfood']]++;

#buy more dog food
@$cart[$items['dogfood']]++;

# look in cart
print_r($cart);

?>
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Post by Stryks »

mickd - I'll give that a whirl and see how I go. You know I actually did play with that but I just couldnt seem to get what I wanted. Hopefully your approach will help.

bokehman - Unfortunately, my cart is much more complex than that, with items being made up of various key components, and multiple optional upgrades / downgrades on multiple categories.

To make it more complex, there is the ability to save a set of options for a product as a custom item for later re-purchase.

The task I am working at here is making sure that if a custom item is added and then a stock item is customised to be the same end product, instead of adding a second item we just increment the existing one; hence the need to compare a multidimensional array of unknown complexity.


Thanks for the feedback guys.
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Post by Stryks »

Here is the recursive function using array_diff

Code: Select all

function arr_identical($array_1, $array_2) {
	$test_1 = array_diff($array_1, $array_2);
	$test_2 = array_diff($array_2, $array_1);
	
	if(empty($test_1) && empty($test_2)) {
		foreach($array_1 as $key=>$value) 
			if(is_array($value)) return arr_identical($value, $array_2[$key]);
			else return true;
	} else return false;
}
I cant for the life of me find a use for array_walk though. it looks so promising but I cant really get it to do anything useful (apart from echoing info);

Any advances on this ?
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Post by Stryks »

I seem to be pumping away at my own thread here. Seems a bit harder to get assistance lately, but I guess you can only ask and hope.

Anyhow ... I'm just updating this in case someone else needs a solution to a similar problem.

The previos code had a bug where it only checked the first element of the array to see if it was an array requiring a iteration. This revision also uses array_diff_assoc to ensure that both the keys and values match.

Code: Select all

function arr_identical($array_1, $array_2) {
   $test_1 = array_diff_assoc($array_1, $array_2);
   $test_2 = array_diff_assoc($array_2, $array_1);
	
   if(empty($test_1) && empty($test_2)) {
      foreach($array_1 as $key=>$value) 
         if(is_array($value)) return arr_identical($value, $array_2[$key]);
   } else return false;
   return true;
}
Cheers
Post Reply