В 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('идентификатор категории', $массив));

[0] => 1
[1] => 5
[2] => 9

Я просто ищу что-то более чистое, чем написание собственной функции на основе foreach. Если ответ - это foreach, то у меня уже есть это на месте.

Редактировать: Я не хочу использовать жестко закодированный ключ, я просто показывал пример вызова к решению проблемы. Спасибо! ^_^

Быстрое решение для 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());
}
Author: Wil Moore III, 2012-05-19

8 answers

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

Большинство языков предоставляют такие типы функций (ищите пакеты, такие как коллекция, итератор или перечисление/перечисляемый)...некоторые предоставляют больше функций, чем другие, и вы обычно увидите, что функции называются по-разному на разных языках (т. Е. Собирать == сопоставлять, уменьшать == складывать). Если функция не существует в вашем языке, вы можете создать ее из существующих.

Что касается вашего тестового случая... мы можем использовать array_reduce для реализации pluck. Первая версия, которую я опубликовал, опиралась на array_map; однако я согласен с @salathe в том, что array_reduce более лаконичен для этой задачи; array_map является приемлемым вариантом, но вы заканчиваете в конце концов, придется делать больше работы. 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);

Выберите версию 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

Мы могли бы использовать устаревшую функцию 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.

 32
Author: Wil Moore III, 2017-05-23 12:09:12

Сопоставление - это то, что вам нужно:

$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, где разрешены анонимные обратные вызовы. Для более ранних версий вам нужно будет определить обратный вызов раньше и передать его имя вместо анонимной функции.

 8
Author: Tadeck, 2012-05-18 22:17:21

Для этого нет встроенной функции, но обычно ее называют "срывать".

 5
Author: Alix Axel, 2012-05-18 21:19:57
<?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.

 5
Author: Rawkode, 2012-05-18 22:20:07

Встроенной функции нет. Но один из них легко сделать с помощью 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);
 3
Author: Madara Uchiha, 2012-05-18 21:23:58

Где находится lisp, когда он вам нужен? На самом деле в 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);
 2
Author: zortacon, 2012-05-18 22:13:04

Начиная с 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'));

Смотрите его онлайн на 3v4l.

Для версий до 5.5 вы можете рассмотреть возможность использования полиполнителя.

 1
Author: bishop, 2016-10-26 15:05:25

Вы можете использовать array_filter и передать функцию, основанную на нужном ключе.

Хотя ответ Тадека намного лучше.

 0
Author: Turnsole, 2012-05-18 21:27:39