Как использовать значения массива в виде ключей без циклов?
Цикл - это много времени, мы все это знаем. Это то, чего я пытаюсь избежать, хотя и в небольших масштабах. Каждый бит помогает. Ну, если это не удалось, конечно:)
К вопросу
У меня есть массив:
array(3) {
'0' => array(2) {
'id' => 1234,
'name' => 'blablabla',
},
'1' => array(2) {
'id' => 1235,
'name' => 'ababkjkj',
},
'2' => array(2) {
'id' => 1236,
'name' => 'xyzxyzxyz',
},
}
Я пытаюсь преобразовать этот массив следующим образом:
array(3) {
'1234' => 'blablabla',
'1235' => 'asdkjrker',
'1236' => 'xyzxyzxyz',
}
Я предполагаю, что это нелегко, но мой разум сейчас разорен, и я не могу думать ни о чем, кроме цикла, чтобы это сделать.
Ответы
Ответ 1
Просто используйте array_combine
вместе с array_column
как
array_combine(array_column($array,'id'), array_column($array,'name'));
Или вы можете просто использовать array_walk
, если у вас есть PHP < 5.5 как
$result = array();
array_walk($array, function($v)use(&$result) {
$result[$v['id']] = $v['name'];
});
Отредактировано:
Для будущего пользователя, у которого есть PHP > 5.5, можно просто использовать array_column
как
array_column($array,'name','id');
Fiddle (array_walk)
Ответ 2
UPD: Предупреждение самое медленное решение! См. Контрольные показатели ниже.
Попробуйте этот код:
$a = array(array('id' => 1234,
'name' => 'blablabla'),
array('id' => 1235,
'name' => 'ababkjkj'),
array('id' => 1236,
'name' => 'xyzxyzxyz'));
var_export(array_reduce($a, function($res, $item) {
$res[$item['id']] = $item['name'];
return $res;
}));
Хорошо работает даже в PHP 5.3. И использует только одну функцию array_reduce
.
UPD:
Вот некоторые тесты (PHP 5.6 над Debian 7 на сервере среднего качества):
$a = [];
for ($i = 0; $i < 150000; $i++) {
$a[$i] = ['id' => $i,
'name' => str_shuffle('abcde') . str_shuffle('01234')];
}
$start = microtime(true);
if (false) {
// 7.7489550113678 secs for 15 000 itmes
$r = array_reduce($a, function($res, $item) {
$res[$item['id']] = $item['name'];
return $res;
});
}
if (false) {
// 0.096649885177612 secs for 150 000 items
$r = array_combine(array_column($a, 'id'),
array_column($a, 'name'));
}
if (true) {
// 0.066264867782593 secs for 150 000 items
$r = [];
foreach ($a as $subarray) {
$r[$subarray['id']] = $subarray['name'];
}
}
if (false) {
// 0.32427287101746 secs for 150 000 items
$r = [];
array_walk($a, function($v) use (&$r) {
$r[$v['id']] = $v['name'];
});
}
echo (microtime(true) - $start) . ' secs' . PHP_EOL;
Итак, как вывод: простая итерация с простым циклом for
является победителем (как упоминалось в этом ответе). На втором месте array_combine
разрешено только для новых версий PHP. И в худшем случае я использую собственное решение с закрытием и array_reduce
.
Ответ 3
Если у вас есть php >= 5.5:
$res = array_combine(array_column($source, 'id'), array_column($source, 'name'));
Если нет - сделайте цикл.
Ответ 4
Используйте array_map, (PHP 4 >= 4.0.6, PHP 5)
[[email protected] tmp]$ cat test.php
<?php
$array = array(
array('id' => 1234,'name' => 'blablabla'),
array('id' => 1235,'name' => 'ababkjkj'),
array('id' => 1236,'name' => 'xyzxyzxyz')
);
$output = array();
array_map(function($_) use (&$output){ $output[$_['id']] = $_['name']; },$array);
// Input
print_r($array);
// Output
print_r($output);
?>
Выход
[[email protected] tmp]$ php test.php
Array
(
[0] => Array
(
[id] => 1234
[name] => blablabla
)
[1] => Array
(
[id] => 1235
[name] => ababkjkj
)
[2] => Array
(
[id] => 1236
[name] => xyzxyzxyz
)
)
Array
(
[1234] => blablabla
[1235] => ababkjkj
[1236] => xyzxyzxyz
)
Ответ 5
Это самый быстрый и простой код здесь до сих пор...
$result = [];
foreach ($input as $subarray) {
$result[$subarray["id"]] = $subarray["name"];
}
Ответ 6
Попробуйте эту функцию:
array_combine(array_column($array,'id'), array_column($array,'name'));