【问题标题】:Slicing a multi-dimensional PHP array across one of its elements跨其中一个元素切片多维 PHP 数组
【发布时间】:2010-09-14 20:50:21
【问题描述】:

比如说你刚刚查询了一个数据库,你收到了这个二维数组。

$results = array(
    array('id' => 1, 'name' => 'red'  , 'spin' =>  1),
    array('id' => 2, 'name' => 'green', 'spin' => -1),
    array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);

我经常发现自己在写这样的循环。

foreach($results as $result)
    $names[] = $result['name'];

我的问题是有没有一种方法可以在不使用循环的情况下获取这个数组 $names?使用回调函数算作使用循环。

这是获取每个字段的更通用示例。

foreach($results as $result)
    foreach($result as $key => $value)
        $fields[$key][] = $value;

【问题讨论】:

标签: php arrays associative-array


【解决方案1】:

简单地说,没有。

您将需要使用循环或回调函数,例如 array_walk

【讨论】:

  • 这不再是真的。 PHP 5.5 提供了一个内置的array_column 函数:)
【解决方案2】:

我对@Devon 的回复投了赞成票,因为确实没有办法使用内置函数来完成您所要求的事情。你能做的最好的就是自己写:

function array_column($array, $column)
{
    $ret = array();
    foreach ($array as $row) $ret[] = $row[$column];
    return $ret;
}

【讨论】:

  • 我的错误是你没有声明ret,即使你在技术上不需要在 PHP 中。 ($ret = array();)
  • @Quentin 请告知回答用户您认为答案有误的地方,而不是悄悄地纠正它。
  • 这是 Mark 关于初始化 $ret 的评论。我赞成马克的评论,并提供了答案的更改并附有解释。我也应该在这里添加评论?
  • 具有讽刺意味的是,PHP 包含一个具有完全相同标签的核心函数array_column()..!!你参与了吗?
  • @Fr0zenFyr 哈哈,不。只是巧合:)
【解决方案3】:

我认为这会做你想做的事

array_uintersect_uassoc

你必须做这样的事情

$results = array(
    array('id' => 1, 'name' => 'red'  , 'spin' =>  1),
    array('id' => 2, 'name' => 'green', 'spin' => -1),
    array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);
$name = array_uintersect_uassoc( $results, array('name' => 'value')  , 0, "cmpKey");
print_r($name);

//////////////////////////////////////////////////
// FUNCTIONS
//////////////////////////////////////////////////
function cmpKey($key1, $key2) {
  if ($key1 == $key2) {
    return 0;
  } else {
    return -1;
  }
}

但是,我无法访问 PHP5,所以我没有对此进行测试。

【讨论】:

  • 这在 PHP5 中对我不起作用。我收到了 Not a valid callback 警告和一个空数组。
  • 它失败了,因为你必须传递一个函数而不是 0。即使我传递一个总是返回 true 或 false 的函数,我仍然没有得到有效的答案。您不能使用数组相交,因为它是数组内部的数组。您可以根据返回类型使用 array_walk 或 array_map。
【解决方案4】:

我对此进行了更多研究,发现 ruby​​ 和原型都有一个称为 array_pluck,2 的函数。有趣的是,array_map 有第二个用途,可以让你做与我在这里想做的相反的事情。我还发现了一个 PHP class 有人正在编写以模拟数组的原型操作。

我会做更多的挖掘工作,如果我没有找到任何其他东西,我会制作一个补丁提交到 internals@lists.php.net 邮件列表,看看他们是否会添加 array_pluck。

【讨论】:

    【解决方案5】:

    从 PHP 5.3 开始,您可以将这个漂亮的调用与 lambda 函数一起使用:

    $names = array_map(function ($v){ return $v['name']; }, $results);
    

    这将返回按“名称”维度切片的数组。

    【讨论】:

    • 您可以在返回的切片维度上额外使用 array_unique 来获取唯一名称。
    【解决方案6】:

    截至 6 月 20 日,PHP-5.5 中有一个新函数 array_column

    例如:

    $records = array(
        array(
            'id' => 2135,
            'first_name' => 'John',
            'last_name' => 'Doe'
        ),
        array(
            'id' => 3245,
            'first_name' => 'Sally',
            'last_name' => 'Smith'
        ),
        array(
            'id' => 5342,
            'first_name' => 'Jane',
            'last_name' => 'Jones'
        ),
        array(
            'id' => 5623,
            'first_name' => 'Peter',
            'last_name' => 'Doe'
        )
    );
    
    
    $firstNames = array_column($records, 'first_name');
    print_r($firstNames);
    

    会回来

    Array
    (
        [0] => John
        [1] => Sally
        [2] => Jane
        [3] => Peter
    )
    

    上述链接中还有更多示例。

    【讨论】:

    • 哇!很高兴找到这个功能。与array_map() 相比,非常方便和容易。不过需要比较性能。
    【解决方案7】:

    你可以这样做:

    $tmp = array_flip($names);
    $names = array_keys($tmp);
    

    【讨论】:

      【解决方案8】:

      对于那些现在不能升级到PHP5.5并且需要这个功能的人,这里是array_column的一个实现。

      function array_column($array, $column){
          $a2 = array();
          array_map(function ($a1) use ($column, &$a2){
              array_push($a2, $a1[$column]);
          }, $array);
          return $a2;
      }
      

      【讨论】:

        【解决方案9】:

        如果你运行的是 5.5 之前的 PHP 版本和array_column(),你可以使用普通 PHP 的官方替换:

        https://github.com/ramsey/array_column

        【讨论】:

          【解决方案10】:

          这是 array_column() 的快速函数替代

          if(!function_exists('array_column')) {
              function array_column($element_name) {
                  $ele =   array_map(function($element) {
                      return $element[$element_name];
                  }, $a);
                  return  $ele;
              }
          }
          

          【讨论】:

            【解决方案11】:

            其他选择

             function transpose(array $array): array
             {
                 $out = array();
                 foreach ($array as $rowkey => $row) {
                    foreach ($row as $colkey => $col) {
                            $out[$colkey][$rowkey] = $col;
                     }
                 }
                    return $out;
             }
            
             function filter_columns(array $arr, string ...$columns): array
             {
                 return array_intersect_key($arr, array_flip($columns));
             }
            

            测试

            $results = array(
                array('id' => 1, 'name' => 'red'  , 'spin' =>  1),
                array('id' => 2, 'name' => 'green', 'spin' => -1),
                array('id' => 3, 'name' => 'blue' , 'spin' => .5)
            );
            
             var_dump(filter_columns(transpose($results),'name'));
             var_dump(filter_columns(transpose($results),'id','name'));
             var_dump(filter_columns(transpose($results),'id','spin'));
            

            【讨论】:

              猜你喜欢
              • 2014-08-25
              • 2020-08-14
              • 2022-01-03
              • 1970-01-01
              • 2020-02-04
              • 2021-12-30
              • 2020-05-03
              • 2021-11-23
              相关资源
              最近更新 更多