PHP - Extracting a property from an array of objects

Php

Php Problem Overview


I've got an array of cats objects:

$cats = Array
    (
        [0] => stdClass Object
            (
                [id] => 15
            ),
        [1] => stdClass Object
            (
                [id] => 18
            ),
        [2] => stdClass Object
            (
                [id] => 23
            )
)

and I want to extract an array of cats' IDs in 1 line (not a function nor a loop).

I was thinking about using array_walk with create_function but I don't know how to do it.

Any idea?

Php Solutions


Solution 1 - Php

If you have PHP 5.5 or later, the best way is to use the built in function array_column():

$idCats = array_column($cats, 'id');

But the son has to be an array or converted to an array

Solution 2 - Php

>Warning create_function() has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged.

You can use the array_map() function.
This should do it:

$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);

As @Relequestual writes below, the function is now integrated directly in the array_map. The new version of the solution looks like this:

$catIds = array_map(function($o) { return $o->id;}, $objects);

Solution 3 - Php

The solution depends on the PHP version you are using. At least there are 2 solutions:

First (Newer PHP versions)

As @JosepAlsina said before the best and also shortest solution is to use array_column as following:

$catIds = array_column($objects, 'id');

Notice: For iterating an array containing \stdClasses as used in the question it is only possible with PHP versions >= 7.0. But when using an array containing arrays you can do the same since PHP >= 5.5.

Second (Older PHP versions)

@Greg said in older PHP versions it is possible to do following:

$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);

But beware: In newer PHP versions >= 5.3.0 it is better to use Closures, like followed:

$catIds = array_map(function($o) { return $o->id; }, $objects);


The difference

First solution creates a new function and puts it into your RAM. The garbage collector does not delete the already created and already called function instance out of memory for some reason. And that regardless of the fact, that the created function instance can never be called again, because we have no pointer for it. And the next time when this code is called, the same function will be created again. This behavior slowly fills your memory...

Both examples with memory output to compare them:

BAD
while (true)
{
	$objects = array_map(create_function('$o', 'return $o->id;'), $objects);

	echo memory_get_usage() . "\n";

    sleep(1);
}

// the output
4235616
4236600
4237560
4238520
...
GOOD
while (true)
{
	$objects = array_map(function($o) { return $o->id; }, $objects);

	echo memory_get_usage() . "\n";

    sleep(1);
}

// the output
4235136
4235168
4235168
4235168
...


This may also be discussed here

https://stackoverflow.com/questions/25808390/memory-leak-is-garbage-collector-doing-right-when-using-create-function-with

Solution 4 - Php

function extract_ids($cats){
    $res = array();
    foreach($cats as $k=>$v) {
        $res[]= $v->id;
    }
    return $res
}

and use it in one line:

$ids = extract_ids($cats);

Solution 5 - Php

>Warning create_function() has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged.

Builtin loops in PHP are faster then interpreted loops, so it actually makes sense to make this one a one-liner:

$result = array();
array_walk($cats, create_function('$value, $key, &$result', '$result[] = $value->id;'), $result)

Solution 6 - Php

CODE

<?php

# setup test array.
$cats = array();
$cats[] = (object) array('id' => 15);
$cats[] = (object) array('id' => 18);
$cats[] = (object) array('id' => 23);

function extract_ids($array = array())
{
    $ids = array();
    foreach ($array as $object) {
        $ids[] = $object->id;
    }
    return $ids;
}

$cat_ids = extract_ids($cats);
var_dump($cats);
var_dump($cat_ids);

?>

OUTPUT

# var_dump($cats);
array(3) {
  [0]=>
  object(stdClass)#1 (1) {
    ["id"]=>
    int(15)
  }
  [1]=>
  object(stdClass)#2 (1) {
    ["id"]=>
    int(18)
  }
  [2]=>
  object(stdClass)#3 (1) {
    ["id"]=>
    int(23)
  }
}

# var_dump($cat_ids);
array(3) {
  [0]=>
  int(15)
  [1]=>
  int(18)
  [2]=>
  int(23)
}

I know its using a loop, but it's the simplest way to do it! And using a function it still ends up on a single line.

Solution 7 - Php

You can do it easily with ouzo goodies

$result = array_map(Functions::extract()->id, $arr);

or with Arrays (from ouzo goodies)

$result = Arrays::map($arr, Functions::extract()->id);

Check out: http://ouzo.readthedocs.org/en/latest/utils/functions.html#extract

See also functional programming with ouzo (I cannot post a link).

Solution 8 - Php

// $array that contain records and id is what we want to fetch a
$ids = array_column($array, 'id');

Solution 9 - Php

    $object = new stdClass();
    $object->id = 1;

    $object2 = new stdClass();
    $object2->id = 2;

    $objects = [
        $object,
        $object2
    ];

    $ids = array_map(function ($object) {
        /** @var YourEntity $object */
        return $object->id;
        // Or even if you have public methods
        // return $object->getId()
    }, $objects);

Output: [1, 2]

Solution 10 - Php

The create_function() function is deprecated as of php v7.2.0. You can use the array_map() as given,

function getObjectID($obj){
    return $obj->id;
}

$IDs = array_map('getObjectID' , $array_of_object);

Alternatively, you can use array_column() function which returns the values from a single column of the input, identified by the column_key. Optionally, an index_key may be provided to index the values in the returned array by the values from the index_key column of the input array. You can use the array_column as given,

$IDs = array_column($array_of_object , 'id');

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionabernierView Question on Stackoverflow
Solution 1 - PhpJosep AlsinaView Answer on Stackoverflow
Solution 2 - PhpGregView Answer on Stackoverflow
Solution 3 - PhpalgorhythmView Answer on Stackoverflow
Solution 4 - PhpSilentGhostView Answer on Stackoverflow
Solution 5 - PhpsoulmergeView Answer on Stackoverflow
Solution 6 - PhpLuke AntinsView Answer on Stackoverflow
Solution 7 - PhpworuView Answer on Stackoverflow
Solution 8 - PhpRai Ahmad FrazView Answer on Stackoverflow
Solution 9 - PhpdaHormezView Answer on Stackoverflow
Solution 10 - PhpKiran ManiyaView Answer on Stackoverflow