5

I have a multidimensional array that looks like this:

Array
(
[0] => Array
    (
        [0] => Array
            (
                [id] => 3
            )

        [1] => Array
            (
                [id] => 1
            )

        [2] => Array
            (
                [id] => 2
            )

        [3] => Array
            (
                [id] => 5
            )

        [4] => Array
            (
                [id] => 4
            )

    )

[1] => Array
    (
        [0] => Array
            (
                [id] => 1
            )

        [1] => Array
            (
                [id] => 3
            )

        [2] => Array
            (
                [id] => 4
            )

        [3] => Array
            (
                [id] => 5
            )

    )

[2] => Array
    (
        [0] => Array
            (
                [id] => 3
            )

    )

)

I need to find a way to return the intersecting value(s). In this case that would be

[id] => 3

The length of the array could be different, so I can't just use array_intersect().

0

4 Answers 4

4

This would be simple if your arrays contained only integers, but as they contain an another array, it gets a bit more complicated. But this should do it:

function custom_intersect($arrays) {
    $comp = array_shift($arrays);
    $values = array();

    // The other arrays are compared to the first array:
    // Get all the values from the first array for comparison
    foreach($comp as $k => $v) {
        // Set amount of matches for value to 1.
        $values[$v['id']] = 1;
    }

    // Loop through the other arrays
    foreach($arrays as $array) {
        // Loop through every value in array
        foreach($array as $k => $v) {
            // If the current ID exists in the compare array
            if(isset($values[$v['id']])) {
                // Increase the amount of matches
                $values[$v['id']]++;
            }
        }
    }

    $result = array();

    // The amount of matches for certain value must be
    // equal to the number of arrays passed, that's how
    // we know the value is present in all arrays.
    $n = count($arrays) + 1;
    foreach($values as $k => $v) {
        if($v == $n) {
            // The value was found in all arrays,
            // thus it's in the intersection
            $result[] = $v;
        }
    }
    return $result;
}

Usage:

$arrays = array(
    array(array('id' => 3), array('id' => 1), array('id' => 2), array('id' => 5), array('id' => 4)),
    array(array('id' => 1), array('id' => 3), array('id' => 4), array('id' => 5)),
    array(array('id' => 3))
);

print_r(custom_intersect($arrays));

Result:

Array
(
    [0] => 3
)

This function isn't perfect: if you have duplicate ID's in one array, it will not work. That would require a bit more code to first make the array values unique, but this will probably work in your case.

Sign up to request clarification or add additional context in comments.

Comments

3

You can use array_uintersect() to get the intersection of arrays using a custom comparison function. You have to call it with call_user_func_array() though, as it expects each array as a separate argument:

//build list of parameters for array_uintersect()
$params = array_merge($input, array('compare_func'));

$result = call_user_func_array('array_uintersect', $params);

function compare_func($a, $b) {
    return $a['id'] - $b['id'];   
}

You can't simply call array_intersect() with call_user_func_array(), because it seems to compare arrays by comparing their string representation (which will always be 'Array').

Comments

1
$a = array(4,3);
$b = array(4,3,2,1);
$c = array(1,2,3,4,5);
$d = array(5,4,3);

$array = array($a,$b,$c,$d);

for ($i=0; $i<count($array); $i++){
    if ($i==0){
        $array2 = $array[$i];
    } else {
        $array2 = array_intersect($array2, $array[$i]);
    }
}

print_r($array2);`

Result:

3,4

Comments

0

As mentioned in one of the comments of the php.net website (array_intersect function).

$a = array(1,2,3,4,5,2,6,1);  /* repeated elements --> $a is not a set */
$b = array(0,2,4,6,8,5,7,9,2,1);  /* repeated elements --> $b is not a set */

$ua = array_merge(array_unique($a));  /* now, $a is a set */
$ub = array_merge(array_unique($b));  /* now, $b is a set */

$intersect = array_merge(array_intersect($ua,$ub));

This will return this array:

Array
(
    [0] => 1
    [1] => 2
    [2] => 4
    [3] => 5
    [4] => 6
)

1 Comment

This wouldn't work in this case unfortunately, as the arrays contain arrays with the key 'id' set. Your works only on arrays with scalar values - this requires an custom function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.