26

我确定这个问题之前已经被问过,我很抱歉没有先找到它。

原始数组:

[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 是答案,我已经准备好了。

编辑:我不想使用硬编码的密钥,我只是展示了一个对解决方案的示例调用。谢谢!^_^

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());
}
4

8 回答 8

33

因此,高阶 集合/迭代器函数(例如pluckfiltereachmap和 friends )的酷之处在于它们可以混合和匹配以组成更复杂的操作集。

大多数语言都提供这些类型的函数(查找诸如集合、迭代器或枚举/可枚举之类的包)...有些提供的函数比其他的多,而且您通常会看到函数在不同语言中的命名方式不同(即 collect == map,减少==折叠)。如果您的语言中不存在某个函数,您可以从确实存在的函数中创建它。

至于你的测试用例......我们可以使用array_reduce来实现pluck。我发布的第一个版本依赖于array_map;但是,我同意@salathe的观点,即array_reduce更简洁地完成这项任务;array_map是一个不错的选择,但你最终不得不做更多的工作。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);

选择您喜欢的采摘版本

$preferredPluck = 'pluck_array_reduce'; // or pluck_array_map

PHP 5.3+ 的“pluck”: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());
}

PHP 5.3+ 的“pluck”: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;
}

这里我们根据我们运行的 PHP 版本选择一个“pluck”版本来调用。如果您运行整个脚本,无论您使用什么版本,都应该得到正确的答案。

$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,看起来这是作为array_column添加到 PHP 5.5 的。

于 2012-05-18T21:31:38.523 回答
9

映射是您需要的:

$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 中工作,其中允许匿名回调。对于早期版本,您需要提前定义回调并传递其名称而不是匿名函数。

于 2012-05-18T21:24:46.830 回答
6

对此没有内置函数,但通常称为“ pluck ”。

于 2012-05-18T21:19:57.723 回答
5
<?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 一起使用。

于 2012-05-18T21:21:52.723 回答
4

从 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 之前的版本,您可以考虑使用polyfill

于 2016-10-26T14:11:57.257 回答
3

没有内置功能。但是很容易用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);
于 2012-05-18T21:23:58.280 回答
2

当你需要时,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);
于 2012-05-18T21:38:10.250 回答
0

您可以使用array_filter,并根据所需的键传入一个函数。

不过,Tadeck 的回答要好得多。

于 2012-05-18T21:22:36.030 回答