Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

** EDIT ** What would happen if I only used arrays, e.g.

array( array('name' => 'bla', 'distance' => '123'); array('name' => 'b123a', 'distance' => '1234214'); );

Would this be easier to find the min value ?

Hi there I'm trying to retrieve the object which has the lowest distance value from an array of objects. This is my data set below;

    [0] => myObjectThing Object
        (
            [name:myObjectThing:private] => asadasd
            [distance:myObjectThinge:private] => 0.9826368952306
        )

    [1] => myObjectThing Object
        (
            [name:myObjectThing:private] => 214gerwert24
            [distance:myObjectThinge:private] => 1.5212312547306
        )

    [2] => myObjectThing Object
        (
            [name:myObjectThing:private] => abc123
            [distance:myObjectThinge:private] => 0.0000368952306
        )

So I'd like to be able to retieve the object which has the smallest distance value. In this case it would be object with name: abc123

Thanks in advance for your help

Andy

share|improve this question
 
"What would happen if I only used arrays?" - you could then array_multisort (au2.php.net/manual/en/function.array-multisort.php). But it wouldn't make a bug difference in this case because you can just use array_walk –  xzyfer Mar 2 '11 at 11:18
1  
you don't need to type "please vote my question" –  llnk Mar 2 '11 at 11:19
 
I'd say the question has managed to stir a good debate, that was all. I've removed now, sorry –  Garbit Mar 2 '11 at 11:21
add comment

6 Answers

Hmm for PHP >= 5.3 I would try something like this:

$Object = array_reduce($data,function($A,$B){
    return $A->distance < $B->distance ? $A : $B;
})

For PHP < 5.3 the fillowing would suffice:

function user_defined_reduce($A,$B){
    return $A->distance < $B->distance ? $A : $B;
}
$Object = array_reduce($data,"user_defined_reduce");
share|improve this answer
 
thats what you call concise :) –  Garbit Mar 2 '11 at 11:18
 
Thanks, Small but effective. –  RobertPitt Mar 2 '11 at 11:21
 
+1 This is what I was going for, stupid me forgot about array_reduce. FYI, he wants to return the object. –  xzyfer Mar 2 '11 at 11:22
 
Works only for PHP 5.3 and above. Care to add version for older PHP? –  Kamil Szot Mar 3 '11 at 10:13
 
Added a version for PHP < 5.3 –  RobertPitt Mar 3 '11 at 10:47
add comment

Previously suggested answers did not explain the need to include an $initial value to array_reduce(). The solution did not work because of it.

This one works for me (PHP 5.3.13):

$array = array(
    array(
        'name' => 'something',
        'value' => 56
    ),
    array(
        'name' => 'else',
        'value' => 54
    ),
    array(
        'name' => 'else',
        'value' => 58
    ),
    array(
        'name' => 'else',
        'value' => 78
    )
);
$object = array_reduce($array, function($a, $b){
    return $a['value'] < $b['value'] ? $a : $b;
}, array_shift($array));

print_r($object);

This will give me:

[0] => Array
(
    [name] => else
    [value] => 54
)

Whereas the previous solution gave me null. I'm assuming that PHP < 5.3 would require a similar initial value to be specified to array_reduce().

share|improve this answer
 
If you're looking for a minimum value with array_reduce in unsorted array, I think there's a chance you won't get the minimum value? –  Dalius Aug 6 '13 at 14:10
add comment

You can't flatten this as it isn't a plain old multi-dimensional array with just the values.

This should work:

$min = $object[0];
for ($i = 1; $i < count($object); $i++)
    if ($object[$i]['distance'] < $min['distance'])
        $min = $object[$i];
share|improve this answer
 
And which object has the minimal value ? You didn't got it - just minimal value. –  hsz Mar 2 '11 at 11:08
 
Thanks for that, I've fixed it. –  Delan Azabani Mar 2 '11 at 11:09
 
If I didn't use objects and just had a massive array would this be easier? Only problem with doing it with a big array is that it's a bit hacky. My only problem with using another loop is that I am already at O(n^2) which will be huge if i wrap another loop in there –  Garbit Mar 2 '11 at 11:11
 
Would it be possible to integrate it into your main loop to avoid pushing past O(n)? Or is your main loop not through the objects? –  Delan Azabani Mar 2 '11 at 11:17
 
It's through another data set, so i'm pulling data then for each element im then making another request for that data. If i added another loop within this i think it would be too cumbersome –  Garbit Mar 2 '11 at 11:20
add comment

This example should give you a hint in the right direction:

<?php

$a = new stdClass();
$a->foo = 2;
$b = new stdClass();
$b->foo = 3;
$c = new stdClass();
$c->foo = 1;

$init = new stdClass();
$init->foo = 1000;

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

var_dump(
    array_reduce(
        $vals,
        function ( $x, $y )
        {
            if ( $x->foo < $y->foo )
            {
                return $x;
            }   
            else
            {
                return $y;
            }   
        },  
        $init
    )   
);  

?>
share|improve this answer
add comment

try:

$myObjectCollection = ...;
$minObject = $myObjectCollection[0]; // or reset($myObjectCollection) if you can't ensure  numeric 0 index

array_walk($myObjectCollection, function($object) use ($minObject) { 
        $minObject = $object->distance < $minObject->distance ? $object : $minObject;
});

but from the looks of your dump. name and distance are private. So you want be able to access them from the object directly using ->. You'll need some kind of getter getDistance()

share|improve this answer
add comment
$objectsArray = array(...); // your objects
$distance     = null;
$matchedObj   = null;

foreach ( $objectsArray as $obj ) {
   if ( is_null($distance) || ( $obj->distance < $distance ) ) {
      $distance   = $obj->distance;
      $matchedObj = $obj;
   }
}

var_dump($matchedObj);

AD EDIT:

If you will use arrays instead of objects, change $obj->distance to $obj['distance'].

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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