В PHP есть функция, которая возвращает массив, состоящий из значения ключа из массива ассоциативных массивов?
Я уверен, что этот вопрос задавался раньше, мои извинения за то, что не нашли его первым.
Исходный массив:
[0] => Array
(
[categoryId] => 1
[eventId] => 2
[eventName] => 3
[vendorName] => 4
)
[1] => Array
(
[categoryId] => 5
[eventId] => 6
[eventName] => 7
[vendorName] => 8
)
[2] => Array
(
[categoryId] => 9
[eventId] => 10
[eventName] => 11
[vendorName] => 12
)
Я надеялся на результат из: print_r(get_values_from_a_key_in_arrays('categoryId', $array));
[0] => 1
[1] => 5
[2] => 9
Я просто ищу что-то более чистое, чем написание собственной функции на основе foreach. Если foreach - это ответ, у меня это уже есть.
Редактировать: я не хочу использовать жестко закодированный ключ, я просто показываю пример вызова решения. Спасибо! ^ _ ^
Quick Grab Solution для PHP 5.3:
private function pluck($key, $data) {
return array_reduce($data, function($result, $array) use($key) {
isset($array[$key]) && $result[] = $array[$key];
return $result;
}, array());
}
8 ответов
Итак, классная вещь в функциях сбора / итераторов высшего порядка, таких как pluck, filter, each, map и friends, заключается в том, что их можно смешивать и сопоставлять для составления более сложного набора операций.
Большинство языков предоставляют такие типы функций (ищите пакеты, такие как collection, iterator или enumeration/enumerable)... некоторые предоставляют больше функций, чем другие, и вы обычно увидите, что функции называются по-разному в разных языках (например, collect == map, уменьшить == раз). Если функция не существует на вашем языке, вы можете создать ее из тех, которые существуют.
Что касается вашего теста... мы можем использовать http://php.net/array_reduce для реализации pluck. Первая версия, которую я разместил, была основана на array_map
; однако я согласен с salathe, что http://php.net/array_reduce более лаконична для этой задачи; array_map - это вариант OK, но в итоге вам придется выполнять больше работы. array_reduce
на первый взгляд может показаться немного странным, но если обратный вызов организован аккуратно, все хорошо.
Менее наивный pluck
также проверил бы, может ли он "вызвать" (функцию / метод) для повторного значения. В наивной реализации ниже мы предполагаем, что структура является хешем (ассоциативный массив).
Это настроит данные тестового примера (Fixtures):
<?php
$data[] = array('categoryId' => 1, 'eventId' => 2, 'eventName' => 3, 'vendorName' => 4);
$data[] = array('categoryId' => 5, 'eventId' => 6, 'eventName' => 7, 'vendorName' => 8);
$data[] = array('categoryId' => 9, 'eventId' => 10, 'eventName' => 11, 'vendorName' => 12);
$data[] = array(/* no categoryId */ 'eventId' => 10, 'eventName' => 11, 'vendorName' => 12);
$data[] = array('categoryId' => false,'eventId' => 10, 'eventName' => 11, 'vendorName' => 12);
$data[] = array('categoryId' => 0.0, 'eventId' => 10, 'eventName' => 11, 'vendorName' => 12);
Выберите версию pluck, которую вы предпочитаете
$preferredPluck = 'pluck_array_reduce'; // or pluck_array_map
"pluck" для PHP 5.3+: array_reduce обеспечивает краткую реализацию, хотя не так легко рассуждать, как версия array_map:
function pluck_array_reduce($key, $data) {
return array_reduce($data, function($result, $array) use($key){
isset($array[$key]) &&
$result[] = $array[$key];
return $result;
}, array());
}
"pluck" для PHP 5.3+: array_map не подходит для этого, поэтому мы должны сделать больше проверок (и это все еще не учитывает много потенциальных случаев):
function pluck_array_map($key, $data) {
$map = array_map(function($array) use($key){
return isset($array[$key]) ? $array[$key] : null;
}, $data);
// is_scalar isn't perfect; to make this right for you, you may have to adjust
return array_filter($map, 'is_scalar');
}
"сорвать" для устаревшего PHP <5.3
Мы могли бы использовать устаревшую функцию create_function; однако, это плохая форма, не рекомендуется, а также не совсем элегантно, поэтому я решил не показывать это.
function pluck_compat($key, $data) {
$map = array();
foreach ($data as $array) {
if (array_key_exists($key, $array)) {
$map[] = $array[$key];
}
}
unset($array);
return $map;
}
Здесь мы выбираем версию "pluck" для вызова на основе версии PHP, которую мы используем. Если вы запустите весь скрипт, вы должны получить правильный ответ, независимо от того, на какой версии вы находитесь.
$actual = version_compare(PHP_VERSION, '5.3.0', '>=')
? $preferredPluck('categoryId', $data)
: pluck_compat('categoryId', $data);
$expected = array(1, 5, 9, false, 0.0);
$variance = count(array_diff($expected, $actual));
var_dump($expected, $actual);
echo PHP_EOL;
echo 'variance: ', $variance, PHP_EOL;
print @assert($variance)
? 'Assertion Failed'
: 'Assertion Passed';
Обратите внимание, что здесь нет конца '?>'. Это потому, что это не нужно. Больше пользы может быть в том, чтобы оставить его, чем оставить в покое.
Кстати, похоже, что это добавляется в PHP 5.5 как array_column.
Картография это то, что вам нужно:
$input = array(
array(
'categoryId' => 1,
'eventId' => 2,
'eventName' => 3,
'vendorName' => 4,
),
array(
'categoryId' => 5,
'eventId' => 6,
'eventName' => 7,
'vendorName' => 8,
),
array(
'categoryId' => 9,
'eventId' => 10,
'eventName' => 11,
'vendorName' => 12,
),
);
$result = array_map(function($val){
return $val['categoryId'];
}, $input);
Или создание функции, которую вы хотели:
function get_values_from_a_key_in_arrays($key, $input){
return array_map(function($val) use ($key) {
return $val[$key];
}, $input);
};
а затем используя его:
$result = get_values_from_a_key_in_arrays('categoryId', $array);
Это будет работать в PHP >= 5.3, где разрешены анонимные обратные вызовы. Для более ранних версий вам нужно будет определить обратный вызов ранее и передать его имя вместо анонимной функции.
Для этого нет встроенной функции, но обычно ее называют " срывать".
<?php
$a = array(
array('a' => 1, 'b' => 2),
array('a' => 2, 'b' => 2),
array('a' => 3, 'b' => 2),
array('a' => 4, 'b' => 2)
);
function get_a($v) {
return $v['a'];
}
var_dump(array_map('get_a', $a));
Вы можете использовать функцию create_function или анонимную функцию (PHP 5.3 >=)
<?php
$a = array(
array('a' => 1, 'b' => 2),
array('a' => 2, 'b' => 2),
array('a' => 3, 'b' => 2),
array('a' => 4, 'b' => 2)
);
var_dump(array_map(create_function('$v', 'return $v["a"];'), $a));
Я написал бы функцию обратного вызова, как описано выше, а затем использовал бы ее с array_map.
Начиная с PHP 5.5, используйте array_column
:
$events = [
[ 'categoryId' => 1, 'eventId' => 2, 'eventName' => 3, 'vendorName' => 4 ],
[ 'categoryId' => 5, 'eventId' => 6, 'eventName' => 7, 'vendorName' => 8 ],
[ 'categoryId' => 9, 'eventId' => 10, 'eventName' => 11, 'vendorName' => 12 ],
];
print_r(array_column($events, 'categoryId'));
Для версий до 5.5 вы можете рассмотреть возможность использования полифилла.
Там нет встроенной функции. Но легко сделать с array_map()
,
$array = array(
array(
"categoryID" => 1,
"CategoryName" => 2,
"EventName" => 3,
"VendorName" => 4
),
array(
"categoryID" => 5,
"CategoryName" => 6,
"EventName" => 7,
"VendorName" => 8
),
array(
"categoryID" => 9,
"CategoryName" => 10,
"EventName" => 11,
"VendorName" => 12
)
);
$newArray = array_map(function($el) {
return $el["categoryID"];
}, $array);
var_dump($newArray);
Где шепот, когда он тебе нужен? На самом деле в php им тоже легко управлять. Просто используйте функцию array_map, как показано ниже.
# bunch o data
$data = array();
$data[0] = array("id" => 100, "name" => 'ted');
$data[1] = array("id" => 200, "name" => 'mac');
$data[2] = array("id" => 204, "name" => 'bub');
# what you want to do to each bit of it
function pick($n) { return($n['id']); }
# what you get after you do that
$map = array_map("pick", $data);
# see for yourself
print_r($map);
Вы можете использовать array_filter и передать функцию, основанную на желаемом ключе.
Ответ Тэдека намного лучше, хотя.