PHP - извлечение свойства из массива объектов - PullRequest
102 голосов
/ 13 июля 2009

У меня есть массив объектов кошек:

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

и я хочу извлечь массив идентификаторов кошек в 1 строку (не функция и не цикл).

Я думал об использовании array_walk с create_function, но я не знаю, как это сделать.

Есть идеи?

Ответы [ 8 ]

147 голосов
/ 13 июля 2009

Вы можете использовать функцию array_map().
Это должно сделать это:

$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);
101 голосов
/ 13 августа 2014

Если у вас PHP 5.5 или новее , лучше всего использовать встроенную функцию array_column():

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

Но сын должен быть массивом или преобразован в массив

72 голосов
/ 12 сентября 2014

Решение зависит от версии PHP, которую вы используете. По крайней мере, есть 2 решения:

Первый (более новые версии PHP)

Как сказал @JosepAlsina ранее, лучшее и самое короткое решение - использовать array_column следующим образом:

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

Примечание: Для итерации array, содержащей \stdClass es, как используется в вопросе, это возможно только с версиями PHP >= 7.0. Но при использовании array, содержащего array s, вы можете сделать то же самое с PHP >= 5.5.

Второй (более старые версии PHP)

@ Грег сказал, что в старых версиях PHP можно сделать следующее:

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

Но будьте осторожны: В более новых версиях PHP >= 5.3.0 лучше использовать Closure s, например:

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


Разница

Первое решение создает новую функцию и помещает ее в оперативную память. Сборщик мусора по какой-то причине не удаляет уже созданный и уже вызванный экземпляр функции из памяти. И это независимо от того, что созданный экземпляр функции никогда не может быть вызван снова, потому что у нас нет указателя на него. И в следующий раз, когда этот код будет вызван, эта же функция будет создана снова. Такое поведение медленно заполняет вашу память ...

Оба примера с выводом памяти для сравнения:

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
...


Это также можно обсудить здесь

Утечка памяти ?! Правильно ли работает сборщик мусора при использовании 'create_function' внутри 'array_map'?

4 голосов
/ 13 июля 2009
function extract_ids($cats){
    $res = array();
    foreach($cats as $k=>$v) {
        $res[]= $v->id;
    }
    return $res
}

и используйте его в одну строку :

$ids = extract_ids($cats);
3 голосов
/ 07 января 2015

Вы можете сделать это легко с вкусностями узо

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

или с массивами (из узоских вкусностей)

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

Выезд: http://ouzo.readthedocs.org/en/latest/utils/functions.html#extract

См. Также функциональное программирование с помощью ouzo (я не могу опубликовать ссылку).

3 голосов
/ 13 июля 2009

КОД

<?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)
}

Я знаю, что он использует цикл, но это самый простой способ сделать это! И используя функцию, она все равно заканчивается в одной строке.

3 голосов
/ 13 июля 2009

Встроенные циклы в PHP быстрее, чем интерпретируемые циклы, поэтому на самом деле имеет смысл сделать этот однострочным:

$result = array();
array_walk($cats, create_function('$value, $key, &$result', '$result[] = $value->id;'), $result)
0 голосов
/ 16 мая 2017
    $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);

Выход : [1, 2]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...