vote up 1 vote down star

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?

flag

3 Answers

vote up 1 vote down check
$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);
link|flag
vote up 4 vote down

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;
}
link|flag
Damn you and your use of alternative snytaxes! (kidding) – Chacha102 Feb 3 at 3:36
+1 For using max() :) I rarely see that get any playtime. – Jonathan Sampson Feb 3 at 3:42
vote up 2 vote down

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.

link|flag
Wow, severely beat to the punch. I need to spend way less time typing. :D – zombat Feb 3 at 3:41
+1 I know the feeling :) – Jonathan Sampson Feb 3 at 3:51

Your Answer

Get an OpenID
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.