Skip to content
Advertisement

array_uintersect() gives unexpected results when callback only returns 0 or 1

I have a custom callback in my array_uintersect() call because I need to case-sensitively compare strings in two elements while comparing rows between two multi-dimensional arrays.

function filterIdenticalEntriesCallback($a, $b) {
    echo "<tr><td>{$a['file']}</td><td>{$b['file']}</td><td>{$a['md5']}</td><td>{$b['md5']}</td></tr>";
    if ( (strcmp($a['file'], $b['file']) == 0 ) && ( strcmp($a['md5'],$b['md5']) == 0)){ 
        return 0;
    }
    return 1;
}

$vieja = array(
        array('file' => 'a', 'md5' => '1'),     //cambia
        array('file' => 'b', 'md5' => '2'),     //igual
        array('file' => 'c', 'md5' => '3'),     //igual
        array('file' => 'd', 'md5' => '4'),     //igual
);

$nueva = array(
        array('file' => 'a', 'md5' => '2'),     //cambia
        array('file' => 'b', 'md5' => '2'),     //igual
        array('file' => 'c', 'md5' => '3'),     //igual
        array('file' => 'd', 'md5' => '4'),     //igual
);

echo "<table>";
$ignorar = array_uintersect($nueva, $vieja, 'filterIdenticalEntriesCallback');
echo "</table>";

echo "<pre>";
print_r($ignorar);
echo "</pre>";
?>

OUTPUT

b   a   2   2
b   c   2   3
d   b   4   2
a   c   2   3
b   a   2   1
b   c   2   3
d   b   4   2
a   c   1   3
c   c   3   3
c   a   3   2
a   a   2   1
a   b   2   2
a   d   2   4
Array
(
    [2] => Array
        (
            [file] => c
            [md5] => 3
        )

)

I can’t understand why this code doesn’t produce the correct output which should be an array with “B”, “C” and “D” elements, because only “A” element is different from $vieja to $nueva…

if I make both “A” elements equals the output is ok….

EDIT:

function filterIdenticalEntriesCallback($a, $b) {
    echo "<tr><td>{$a['file']}</td><td>{$b['file']}</td><td>{$a['md5']}</td><td>{$b['md5']}</td></tr>";
    if (strcmp($a['file'], $b['file']) == 0 ){ 
        if ( strcmp($a['md5'],$b['md5']) == 0)
            return 0;
        else return 1;
    } else return -1;
}

Using this callback is working ok, but I still don’t understand why… what -1 and 1 callback results means to the function? I mean, I need only equal values… which are when callback return 0… I don’t need other cases…

Advertisement

Answer

The filter that works for me:

function filterIdenticalEntriesCallback($a, $b) {
        $cmp = strcmp($a['file'], $b['file']);
        if($cmp==0) {
                return strcmp($a['md5'], $b['md5']);
        } else {
                return $cmp;
        }
}

Because of the way intersect works internally, you must return a negative number if the first is less than the second, 0 if they are the same, and a positive number if the first is greater than the second. This has been observed before by nate.


A neater filter function:

function filterIdenticalEntriesCallback($a, $b) {
        if ($a==$b) {
                return 0;
        } else {
                return $a<$b ? -1 : 1;
        }
}

This works because of the way PHP does comparing. In theory, this comparing function would work for ANY two objects of the same type where you want to make sure all of the attributes and their values are the same.

Or the same thing as a one liner:

function filterIdenticalEntriesCallback($a, $b) {
        return $a == $b ? 0 : ($a < $b ? -1 : 1);
}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement