Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use array_diff_assoc() or get difference of multidimensional arrays

I have two arrays and these arrays contain information about id, linklabel and url in the following format:

$pageids = [
    ['id' => 1, 'linklabel' => 'Home', 'url' => 'home'],
    ['id' => 2, 'linklabel' => 'Graphic Design', 'url' => 'graphicdesign'],
    ['id' => 3, 'linklabel' => 'Other Design', 'url' => 'otherdesign'],
    ['id' => 6, 'linklabel' => 'Logo Design', 'url' => 'logodesign'],
    ['id' => 15, 'linklabel' => 'Content Writing', 'url' => 'contentwriting'],
];

$parentpage = [
    ['id' => 2, 'linklabel' => 'Graphic Design', 'url' => 'graphicdesign'],
    ['id' => 3, 'linklabel' => 'Other Design', 'url' => 'otherdesign'],
];

I'm now trying to compare these two in order to find the information that is in $pageids but NOT in $parentpage - this will then make up another array called $pageWithNoChildren. However when I use the following code:

$pageWithNoChildren = array_diff_assoc($pageids,$parentpage);

The array_diff_assoc() runs on the first level of the arrays and therefore sees that both $pageids and $parentpages have a [0] and [1] key so it ignores them and returns all the information from $pageids from [2] onwards. However I want it to look at the content of the nested arrays and compare those e.g. I need it to see which id, linklabel and url are in $pageids and not in $parentpages and return those values.

How can I get the array_diff_assoc() to run on the keys of the nested arrays and not the keys of the first arrays so the final result is an array that contains the contents of the [0], [3] and [4] arrays from $pageids?

Expected Result:

array (
  0 => 
  array (
    'id' => 1,
    'linklabel' => 'Home',
    'url' => 'home',
  ),
  3 => 
  array (
    'id' => 6,
    'linklabel' => 'Logo Design',
    'url' => 'logodesign',
  ),
  4 => 
  array (
    'id' => 15,
    'linklabel' => 'Content Writing',
    'url' => 'contentwriting',
  ),
)
like image 827
Smokescreen Avatar asked Mar 12 '14 14:03

Smokescreen


2 Answers

To check multi-deminsions try something like this:

$pageWithNoChildren = array_map('unserialize',
    array_diff(array_map('serialize', $pageids), array_map('serialize', $parentpage)));
  • array_map() runs each sub-array of the main arrays through serialize() which converts each sub-array into a string representation of that sub-array
    • the main arrays now have values that are not arrays but string representations of the sub-arrays
  • array_diff() now has a one-dimensional array for each of the arrays to compare
  • after the difference is returned array_map() runs the array result (differences) through unserialize() to turn the string representations back into sub-arrays

Q.E.D.

like image 159
AbraCadaver Avatar answered Nov 11 '22 18:11

AbraCadaver


Very nice solution from @AbraCadaver, but like I've stated in the comments, there might be cases when the elements of associative arrays are not in the same order everywhere, thus a custom function which will sort them by index / key first is handy:

function sortAndSerialize($arr){
    ksort($arr);
    return serialize($arr);
}

array_map('unserialize', array_diff(array_map('sortAndSerialize', $pageids), array_map('sortAndSerialize', $parentpage)));
like image 32
qdev Avatar answered Nov 11 '22 17:11

qdev