views:

1153

answers:

6

I have an array in this format:

Array
(
    [0] => Array
        (
            [id] => 117
            [name] => Networking
            [count] => 16
        )

    [1] => Array
        (
            [id] => 188
            [name] => FTP
            [count] => 23
        )

    [2] => Array
        (
            [id] => 189
            [name] => Internet
            [count] => 48
        )

)

Is there a good way to retrieve the minimum and maximum values of 'count'? I could do this using a few loops but I thought there may be a better way.

A: 

You could use the max() and min() functions.

Mr. Smith
+1 because this lead me to my answer.
MitMaro
A: 

You can use the max/min functions as they will return an array containing the maximum/minimum of each index. Your example should return array(189, 'Networking ', 48) for max. You could then grab the count from that array.


Update this doesn't work as I had excepted. The manual page example is misleading and the example about gives the correct result using max but that is just a coincidence.

MitMaro
To be more specific, it will actually return the keys properly mapped as well - so you can do `max($array)['count']` and `min($array)['count']`
Amber
Dav: I get a parse error when I try that. Perhaps your thinking of Python.
MitMaro
Maybe you should re-read the question MitMaro! :P
Mr. Smith
Oh, sorry MitMaro - forgot that PHP won't let you invoke indexing directly on a function result. You *can* do `$temp = max($array); print($temp['count']);` though.
Amber
I wish PHP had that feature, it is a nice one.
MitMaro
Are you sure your code does what you think it does?<?php$data = array();$data[] = array('id' => 190, 'count' => 16);$data[] = array('id' => 188, 'count' => 8);$data[] = array('id' => 195, 'count' => 6);print_r(max($data));[~]> php test.php Array( [id] => 195 [count] => 6)So, no, it does NOT return the max of reach index.
Anti Veeranna
Sorry, this is nonsense - please see my answer for details.
Stefan Gehrig
Your right Anti Veeranna the manual pages give a very misleading example which happens to give the same misleading result with the example above.
MitMaro
A: 

What did you do with a few loops? One is quite enough :)

  1. Get the first element, assing the count to both $min and $max
  2. iterate over the rest, compare count to each $min and $max, if smaller/larger, assign the new count value
Anti Veeranna
+2  A: 

In contrast to what others have posted, you cannot use the min()/max() functions for this problem as these functions do not understand the datastructure (array) which are passed in. These functions only work for scalar array elements.


BEGIN EDIT

The reason why the use of min() and max() seem to yield the correct answer is related to type-casting arrays to integers which is an undefined behaviour:

The behaviour of converting to integer is undefined for other types. Do not rely on any observed behaviour, as it can change without notice.

My statement above about the type-casting was wrong. Actually min() and max() do work with arrays but not in the way the OP needs them to work. When using min() and max() with multiple arrays or an array of arrays elements are compared element by element from left to right:

$val = min(array(2, 4, 8), array(2, 5, 1)); // array(2, 4, 8)
/*
 * first element compared to first element: 2 == 2
 * second element compared to second element: 4 < 5
 * first array is considered the min and is returned
 */

Translated into the OP's problem this shows the reason why the direct use of min() and max() seems to yield the correct result. The arrays' first elements are the id-values, therefore min() and max() will compare them first, incidentally resulting in the correct result because the lowest id is the one with the lowest count and the highest id is the one with the highest count.

END EDIT


The correct way would be to use a loop.

$a = array(
        array('id' => 117, 'name' => 'Networking', 'count' => 16),
        array('id' => 188, 'name' => 'FTP', 'count' => 23),
        array('id' => 189, 'name' => 'Internet', 'count' => 48)
);
$min = PHP_INT_MAX;
$max = 0;
foreach ($a as $i) {
    $min = min($min, $i['count']);
    $max = max($max, $i['count']);
}
Stefan Gehrig
From the manual page for max `$val = max(array(2, 4, 8), array(2, 5, 7)); // array(2, 5, 7)`. Read it.
MitMaro
Your answer is the correct one though not for the reason you stated about. `min` and `max` do handle arrays correctly and do not cast them to integers, the manual gives more detail.
MitMaro
@MitMaro: You're right - my assumption or reasoning about the use of arrays in min() and max() was wrong. I edited my answer and removed the wrong statement.
Stefan Gehrig
A: 

Looks like you can't use max() on a 2D array. It just returns the largest array, not the max() of each index (as being mentioned in a few answers).

So:

$count = array();
foreach($arr as $_arr) {
    $count[] = $_arr['count'];
}
var_dump(max($count), min($count));
bucabay
A: 

Is there an equivalent build-in function to that one? (even without the test capability)

/**
 * extracts a column from a 2D array, with an optional selection over another column
 *
 * @param $aArray     array to extract from
 * @param $aColName   name of the column to extract, ex. 'O_NAME'
 * @param $aColTest   (optional) name of the column to make the test on, ex. 'O_ID'
 * @param $aTest      (optional) string for the test ex. ">= 10", "=='".$toto."'"
 * @return            1D array with only the extracted column
 * @access public
 */

 function extractColFromArray($aArray, $aColName, $aColTest="", $aTest="") {
  $mRes = array();
  foreach($aArray as $row) {
   if (($aColTest == "") || (eval("return " . $row[$aColTest] . $aTest . ";" )) ) {
    $mRes[] = $row[$aColName];
   }
  }
  return $mRes;
 } // extractColFromArray
Alex