views:

228

answers:

4

Hi,

This is my array

Array
(
    [0] => Array
        (
            [sample_id] => 3
            [time] => 2010-05-30 21:11:47
        )

    [1] => Array
        (
            [sample_id] => 2
            [time] => 2010-05-30 21:11:47
        )

    [2] => Array
        (
            [sample_id] => 1
            [time] => 2010-05-30 21:11:47
        )
)

And I want to get all the sample_ids in one array. can someone please help ?

Can this be done without for loops (because arrays are very large).

+2  A: 

This is a problem I've had MANY times. There isn't an easy way to flatten arrays in PHP. You'll have to loop them adding them to another array. Failing that rethink how you're working with the data to use the original structure and not require the flatten.

EDIT: I thought I'd add a bit of metric information, I created an array $data = array(array('key' => value, 'value' => other_value), ...); where there were 150,000 elements in my array. I than ran the 3 typical ways of flattening

$start = microtime();
$values = array_map(function($ele){return $ele['key'];}, $data);
$end = microtime();

Produced a run time of: Run Time: 0.304405 Running 5 times averaged the time to just below 0.30

$start = microtime();
$values = array();
foreach ($data as $value) {
    $values[] = $value['key'];
}
$end = microtime();

Produced a run time of Run Time: 0.167301 with an average of 0.165

$start = microtime();
$values = array();
for ($i = 0; $i < count($data); $i++) {
    $values[] = $data[$i]['key'];
}
$end = microtime();

Produced a run time of Run Time: 0.353524 with an average of 0.355

In every case using a foreach on the data array was significantly faster. This is likely related to the overhead of the execution of a function for each element in the array for hte array_map() implementation.

Further Edit: I ran this testing with a predefined function. Below are the average numbers over 10 iterations for 'On the Fly' (defined inline) and 'Pre Defined' (string lookup).

Averages:
  On the fly: 0.29714539051056
  Pre Defined: 0.31916437149048
Matt S
Indeed. `array_map` is counterproductive in usually not faster than a foreach loop because it has the overhead of calling a userland function for every element of the array.
Artefacto
I'd be interested in seeing how a separate callback (i.e. 'get_sample_id' from below) stacks up. That has to do a string->function lookup, while the lambda solution [uses](http://www.php.net/manual/en/reserved.classes.php#reserved.classes.closure) the magic [__invoke](http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.invoke).
Matthew Flaschen
+3  A: 
$ids = array_map(function($el){return $el["sample_id"];}, $array);

Or in earlier versions:

function get_sample_id($el){return $el["sample_id"];}
$ids = array_map('get_sample_id', $array);

However, this is probably not going to be faster.

Matthew Flaschen
Really nice, but requires PHP5.3
ThiefMaster
An interesting idea, it still 'loops' the array just using PHP's optimized low level functions.
Matt S
great! this is what I was doing but I was writing a function and then adding a callback there, never new that we can write a function directly in the parameters :) Cheers !
atif089
@ThiefMaster: Can also be done in PHP < 5.3 if you define a "normal" function.
Felix Kling
This basically *is* a `for` loop, but hidden.
Seb
@Matt - yeah it loops but I think this should be faster. Anyways I'll benchmark it soon and let you know
atif089
@Matt, @Seb, @atif089: When dealing with arrays, loops at a certain level cannot be avoided anyway. You cannot access multiple locations in memory at once.
Felix Kling
@Felix - yeah got it. Actually im an in house programmer so was thinking how the big guys do it. Btw. the benchmark results are `0.00002408 secs` for `foreach` loop and `0.00004101 secs` for `array_map`
atif089
@atif089 try with bigger arrays; those are certainly within the margin of error.
Artefacto
See my benchmark below for a full detailed list of the options.
Matt S
A: 

I don't think you'll have any luck doing this without loops. If you really don't want to iterate the whole structure, I'd consider looking for a way to alter your circumstances...

Can you generate the sample_id data structure at the same time the larger array is created?

Do you really need an array of sample_id entries, or is that just a means to an end? Maybe there's a way to wrap the data in a class that uses a cache and a cursor to keep from iterating the whole thing when you only need certain pieces?

grossvogel
For this I have to make 2 queries to database, one to pull the large arrays and one to pull the sample ids.
atif089
Does your database query return one giant associative array, or are you looping through result sets to construct that big array? If the latter, then you can pull the sample_id values during that loop. If the former, what kind of database api are you using?
grossvogel
+2  A: 

no array manitulation can be done without a loop.
if you can't see a loop, it doesn't mean it's absent. I can make a function

array_summ($array) {
  $ret=0;
  foreach ($array as $value) $ret += $value;
  return $ret;
}

and then call it array_summ($arr) without any visible loops. But don't be fooled by this. There is loop. Every php array function iterate array as well. You just don't see it.

So, the real solution you have to look for, is not the magic function but reducing these arrays.
From where it came? From database most likely.
Consider to make a database to do all the calculations. It will save you much more time than any PHP bulit in function

Col. Shrapnel