views:

762

answers:

3

I'm trying to select the maximum value for a particular key in a multidimensional array. I'm having trouble "getting to" the key in question...

So, the array (which is much more lengthy than what I'm posting here)

[0] => stdClass Object
    (
        [id] => 70
        [cust] => 4
        [dnum] => 1
        [upper] => Array
            (
                [0] => 66
            )

    )
[1] => stdClass Object
    (
        [id] => 43
        [cust] => 42
        [dnum] => 2
        [upper] => Array
            (
                [0] => 77
            )

    )
[2] => stdClass Object
    (
        [id] => 12
        [cust] => 3
        [dnum] => 0
        [upper] => Array
            (
                [0] => 99
            )

    )

I'm trying to find the maximum "dnum" value across the entire array, so in this example, $max = 2. I know that the max function allows me to do this, but I'm not sure how to reference the dnum element without putting the whole thing in a foreach loop, and if I do that, then max wouldn't be the function to use, right?

So, I can't exactly do this:

$max = max($myarray[]->dnum);

Is there a way for me to do this without having to recreate the entire array?

+1  A: 
$max = 0;
foreach($array as $obj)
{
    if($obj->dnum > $max)
    {
        $max = $obj->dnum;
    }
}

That function would work correctly if your highest number is negative.

Because you are using an object, which can have custom properties/structures, I don't believe there are really any 'predefined' functions you can use to get it. Might as well just use a foreach loop.

You really can't get away from a foreach loop, as even internal functions use a foreach loop, it is just behind the scenes.

Another solution is

$numbers = array();
foreach($array as $obj)
{
    $numbers[] = $obj->dnum;
}
$max = max($numbers);
Chacha102
+4  A: 

In PHP 5.2 the only way to do this is to loop through the array.

$max = null;
foreach ($arr as $item) {
  $max = $max === null ? $item->dnum : max($max, $item->dnum);
}

Note: I've seeded the result with 0 because if all the dnum values are negative then the now accepted solution will produce an incorrect result. You need to seed the max with something sensible.

Alternatively you could use array_reduce():

$max = array_reduce($arr, 'max_dnum', -9999999);

function max_denum($v, $w) {
  return max($v, $w->dnum);
}

In PHP 5.3+ you can use an anonymous function:

$max = array_reduce($arr, function($v, $w) {
  return max($v, $w->dnum)
}, -9999999);

You can use array_map() too:

$max = max(array_map($arr, 'get_dnum'));

function get_dnum($a) {
  return $a->dnum;
}
cletus
Damn you and your use of alternative snytaxes! (kidding)
Chacha102
+1 For using `max()` :) I rarely see that get any playtime.
Jonathan Sampson
+2  A: 

The simplest way is probably your initial thought, which is to loop your array once, and pull out all the dnum keys into a separate array, then call max() on that:

$out = array();
foreach($myarray as $obj) {
    $out[] = $obj->dnum;
}
echo max($out);

You could do it without creating a separate array, but you'll end up calling max() a lot more often. Performance/memory usage will be different between the two, you could always benchmark it:

$first = $myarray[0];  //assume zero start index
$max = $first->dnum;
foreach($myarray as $obj) {
    $max = max($max,$obj->dnum);
}
echo $max;

The only other way you could go about it would be to sort your array using usort() and a custom sorting function based on the object dnum properties. This is probably going to be much slower than just looping your array however, so I don't think I'd recommend it unless you needed the array sorted as a side effect.

zombat
Wow, severely beat to the punch. I need to spend way less time typing. :D
zombat
+1 I know the feeling :)
Jonathan Sampson