Ответ 1
Вы можете использовать функцию array_map()
.
Это должно сделать это:
$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);
У меня есть массив объектов кошек:
$cats = Array
(
[0] => stdClass Object
(
[id] => 15
),
[1] => stdClass Object
(
[id] => 18
),
[2] => stdClass Object
(
[id] => 23
)
)
и я хочу извлечь массив идентификаторов кошек в 1 строку (а не функцию или цикл).
Я думал об использовании array_walk
с create_function
, но я не знаю, как это сделать.
Любая идея?
Вы можете использовать функцию array_map()
.
Это должно сделать это:
$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);
Если у вас PHP 5.5 или новее, лучший способ - использовать встроенную функцию array_column()
:
$idCats = array_column($cats, 'id');
Но сын должен быть массивом или преобразован в массив
Решение зависит от используемой вами версии PHP. По крайней мере, есть два решения:
Как сказал @JosepAlsina перед лучшим, а также самым коротким решением, следует использовать array_column
следующим образом:
$catIds = array_column($objects, 'id');
Примечание:
Для итерации array
, содержащей \stdClass
es, как используется в вопросе, возможно только с версиями PHP >= 7.0
. Но при использовании array
, содержащего array
, вы можете сделать то же самое с PHP >= 5.5
.
@Greg сказал в старых версиях PHP, что можно сделать следующее:
$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);
Но будьте осторожны: в новых версиях PHP >= 5.3.0
лучше использовать Closure
s, например follow:
$catIds = array_map(function($o) { return $o->id; }, $objects);
Первое решение создает новую функцию и помещает ее в вашу оперативную память. По какой-то причине сборщик мусора не удаляет уже созданный и уже вызванный экземпляр функции из памяти. И в следующий раз, когда вызывается этот код, эта же функция будет создана снова. Такое поведение медленно заполняет вашу память...
Оба примера с выводом памяти для их сравнения:
while (true)
{
$objects = array_map(create_function('$o', 'return $o->id;'), $objects);
echo memory_get_usage() . "\n";
sleep(1);
}
4235616
4236600
4237560
4238520
...
while (true)
{
$objects = array_map(function($o) { return $o->id; }, $objects);
echo memory_get_usage() . "\n";
sleep(1);
}
4235136
4235168
4235168
4235168
...
Утечка памяти?! Правильно ли сборщик мусора, используя 'create_function' в 'array_map'?
function extract_ids($cats){
$res = array();
foreach($cats as $k=>$v) {
$res[]= $v->id;
}
return $res
}
и использовать его в одной строке:
$ids = extract_ids($cats);
Вы можете легко сделать это с помощью ouzo goodies
$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 (я не могу опубликовать ссылку).
Встроенные петли в PHP быстрее интерпретируют циклы, поэтому на самом деле имеет смысл сделать это однострочным:
$result = array();
array_walk($cats, create_function('$value, $key, &$result', '$result[] = $value->id;'), $result)
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)
}
Я знаю, что он использует цикл, но это самый простой способ сделать это! И используя функцию, она все равно заканчивается на одной строке.
$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]