Ответ 1
Итак, классная вещь о более высокого порядка коллекция/функции итератора, такие как pluck, filter, each, map, и друзья в том, что их можно смешивать и сопоставлять, чтобы составить более сложный набор операций.
Большинство языков предоставляют эти типы функций (ищите пакеты, такие как сбор, итератор или перечисление/перечисляемые)... некоторые предоставляют больше функций, чем другие, и вы обычно увидите, что функции называются по-разному на разных языках (т.е. collect = = map, уменьшите == fold). Если функция не существует на вашем языке, вы можете создать ее из тех, которые существуют.
Что касается вашего тестового примера... мы можем использовать array_reduce для реализации pluck. Первая версия, которую я написал, основывалась на array_map
; однако я согласен с @salathe, что array_reduce является более кратким для этого задача; array_map - это вариант OK, но в конце концов вам нужно больше работать. array_reduce
может выглядеть немного странно, но если обратный вызов аккуратно организован, все хорошо.
Менее наивный pluck
также проверит, может ли он "вызывать" (функцию/метод) на итерированном значении. В наивной реализации ниже мы предполагаем, что структура является хешем (ассоциативный массив).
Это позволит настроить тестовые данные (светильники):
<?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);
Выберите версию, которую вы предпочитаете
$preferredPluck = 'pluck_array_reduce'; // or pluck_array_map
"pluck" для PHP 5.3+: array_reduce обеспечивает краткую реализацию, хотя и не так просто рассуждать о версии массива:
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, которую мы запускаем. Если вы запустите весь script, вы должны получить правильный ответ независимо от того, в какой версии вы находитесь.
$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';
Обратите внимание, что окончание '? > ' отсутствует. Это потому, что это не нужно. Более хорошее может состоять в том, чтобы оставить его, а не держать его вокруг.
FWIW, похоже, что это добавляется к PHP 5.5 как array_column.