• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • array_column()

    (PHP 5 >= 5.5.0, PHP 7)

    返回数组中指定的一列

    说明

    array_column(array $input,mixed $column_key[,mixed $index_key= null]): array

    array_column()返回$input数组中键值为$column_key的列,如果指定了可选参数$index_key,那么$input数组中的这一列的值将作为返回数组中对应值的键。

    参数

    $input

    需要取出数组列的多维数组。如果提供的是包含一组对象的数组,只有 public 属性会被直接取出。为了也能取出 private 和 protected 属性,类必须实现__get()__isset()魔术方法。

    $column_key

    需要返回值的列,它可以是索引数组的列索引,或者是关联数组的列的键,也可以是属性名。也可以是NULL,此时将返回整个数组(配合$index_key参数来重置数组键的时候,非常管用)

    $index_key

    作为返回数组的索引/键的列,它可以是该列的整数索引,或者字符串键值。

    返回值

    从多维数组中返回单列数组。

    更新日志

    版本说明
    7.0.0$input参数现在可以是包含对象的数组。

    范例

    从结果集中取出first names列

    <?php
    // Array representing a possible record set returned from a database
    $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',
        )
    );
     
    $first_names = array_column($records, 'first_name');
    print_r($first_names);
    ?>
    

    以上例程会输出:

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

    从结果集中总取出last names列,用相应的id作为键值

    <?php
    // Using the $records array from Example #1
    $last_names = array_column($records, 'last_name', 'id');
    print_r($last_names);
    ?>
    

    以上例程会输出:

    Array
    (
        [2135] => Doe
        [3245] => Smith
        [5342] => Jones
        [5623] => Doe
    )
    

    username 列是从对象获取 public 的"username"属性

    <?php
    class User
    {
        public $username;
        public function __construct(string $username)
        {
            $this->username = $username;
        }
    }
    $users = [
        new User('user 1'),
        new User('user 2'),
        new User('user 3'),
    ];
    print_r(array_column($users, 'username'));
    ?>
    

    以上例程会输出:

    Array
    (
        [0] => user 1
        [1] => user 2
        [2] => user 3
    )
    

    获取 username 列,从对象通过魔术方法__get()获取 private 的"username"属性。

    <?php
    class Person
    {
        private $name;
        public function __construct(string $name)
        {
            $this->name = $name;
        }
        public function __get($prop)
        {
            return $this->$prop;
        }
        public function __isset($prop) : bool
        {
            return isset($this->$prop);
        }
    }
    $people = [
        new Person('Fred'),
        new Person('Jane'),
        new Person('John'),
    ];
    print_r(array_column($people, 'name'));
    ?>
    

    以上例程会输出:

    Array
    (
        [0] => Fred
        [1] => Jane
        [2] => John
    )
    
    如果不提供__isset(),会返回空数组。

    参见

    • » Recommended userland implementation for PHP lower than 5.5
    if array_column does not exist the below solution will work.
    if(!function_exists("array_column"))
    {
      function array_column($array,$column_name)
      {
        return array_map(function($element) use($column_name){return $element[$column_name];}, $array);
      }
    }
    Because the function was not available in my version of PHP, I wrote my own version and extended it a little based on my needs.
    When you give an $indexkey value of -1 it preserves the associated array key values.
    EXAMPLE:
    $sample = array(
      'test1' => array(
        'val1' = 10,
        'val2' = 100
      ),
      'test2' => array(
        'val1' = 20,
        'val2' = 200
      ),
      'test3' => array(
        'val1' = 30,
        'val2' = 300
      )
    );
    print_r(array_column_ext($sample,'val1'));
    OUTPUT:
    Array
    (
      [0] => 10
      [1] => 20
      [2] => 30
    )
    print_r(array_column_ext($sample,'val1',-1));
    OUTPUT:
    Array
    (
      ['test1'] => 10
      ['test2'] => 20
      ['test3'] => 30
    )
    print_r(array_column_ext($sample,'val1','val2'));
    OUTPUT:
    Array
    (
      [100] => 10
      [200] => 20
      [300] => 30
    )
    <?php
    function array_column_ext($array, $columnkey, $indexkey = null) {
      $result = array();
      foreach ($array as $subarray => $value) {
        if (array_key_exists($columnkey,$value)) { $val = $array[$subarray][$columnkey]; }
        else if ($columnkey === null) { $val = $value; }
        else { continue; }
          
        if ($indexkey === null) { $result[] = $val; }
        elseif ($indexkey == -1 || array_key_exists($indexkey,$value)) {
          $result[($indexkey == -1)?$subarray:$array[$subarray][$indexkey]] = $val;
        }
      }
      return $result;
    }
    ?>
    
    You can also use array_map fucntion if you haven't array_column().
    example:
    $a = array(
      array(
        'id' => 2135,
        'first_name' => 'John',
        'last_name' => 'Doe',
      ),
      array(
        'id' => 3245,
        'first_name' => 'Sally',
        'last_name' => 'Smith',
      )
    );
    array_column($a, 'last_name');
    becomes
    array_map(function($element){return $element['last_name'];}, $a);
    This function does not preserve the original keys of the array (when not providing an index_key).
    You can work around that like so:
    <?php
    // instead of
    array_column($array, 'column');
    // to preserve keys
    array_combine(array_keys($array), array_column($array, 'column'));
    ?>
    
    Some remarks not included in the official documentation.
    1) array_column does not support 1D arrays, in which case an empty array is returned.
    2) The $column_key is zero-based.
    3) If $column_key extends the valid index range an empty array is returned.
    <?php
    # for PHP < 5.5 
    # AND it works with arrayObject AND array of objects
    if (!function_exists('array_column')) {
      function array_column($array, $columnKey, $indexKey = null)
      {
        $result = array();
        foreach ($array as $subArray) {
          if (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
            $result[] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
          } elseif (array_key_exists($indexKey, $subArray)) {
            if (is_null($columnKey)) {
              $index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
              $result[$index] = $subArray;
            } elseif (array_key_exists($columnKey, $subArray)) {
              $index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
              $result[$index] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
            }
          }
        }
        return $result;
      }
    }
    ?>
    
    array_column implementation that works on multidimensional arrays (not just 2-dimensional):
    <?php
    function array_column_recursive(array $haystack, $needle) {
      $found = [];
      array_walk_recursive($haystack, function($value, $key) use (&$found, $needle) {
        if ($key == $needle)
          $found[] = $value;
      });
      return $found;
    }
    Taken from https://github.com/NinoSkopac/array_column_recursive
    My version is closer to the original than http://github.com/ramsey/array_column
    <?php
    /**
     * Provides functionality for array_column() to projects using PHP earlier than
     * version 5.5.
     * @copyright (c) 2015 WinterSilence (http://github.com/WinterSilence)
     * @license MIT
     */
    if (!function_exists('array_column')) {
      /**
       * Returns an array of values representing a single column from the input
       * array.
       * @param array $array A multi-dimensional array from which to pull a
       *   column of values.
       * @param mixed $columnKey The column of values to return. This value may
       *   be the integer key of the column you wish to retrieve, or it may be
       *   the string key name for an associative array. It may also be NULL to
       *   return complete arrays (useful together with index_key to reindex
       *   the array).
       * @param mixed $indexKey The column to use as the index/keys for the
       *   returned array. This value may be the integer key of the column, or
       *   it may be the string key name.
       * @return array
       */
      function array_column(array $array, $columnKey, $indexKey = null)
      {
        $result = array();
        foreach ($array as $subArray) {
          if (!is_array($subArray)) {
            continue;
          } elseif (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
            $result[] = $subArray[$columnKey];
          } elseif (array_key_exists($indexKey, $subArray)) {
            if (is_null($columnKey)) {
              $result[$subArray[$indexKey]] = $subArray;
            } elseif (array_key_exists($columnKey, $subArray)) {
              $result[$subArray[$indexKey]] = $subArray[$columnKey];
            }
          }
        }
        return $result;
      }
    }
    ?>
    
    array_column() will return duplicate values. 
    Instead of having to use array_unique(), use the $index_key as a hack.
    **Caution: This may get messy when setting the $column_key and/or $index_key as integers.**
    <?php
    $records = [
        [ 'id' => 2135, 'first_name' => 'John' ],
      [ 'id' => 3245, 'first_name' => 'Sally' ],
      [ 'id' => 5342, 'first_name' => 'Jane' ],
      [ 'id' => 5623, 'first_name' => 'Peter' ],
        [ 'id' => 6982, 'first_name' => 'Sally' ]
    ];
    print_r(array_unique(array_column($records, 'first_name')));
    // Force uniqueness by making the key the value.
    print_r(array_column($records, 'first_name', 'first_name'));
    print_r(array_column($records, 'id', 'first_name'));
    // Returns
    /*
    Array
    (
      [0] => John
      [1] => Sally
      [2] => Jane
      [3] => Peter
    )
    Array
    (
      [John] => John
      [Sally] => Sally
      [Jane] => Jane
      [Peter] => Peter
    )
    Array
    (
      [John] => 2135
      [Sally] => 6982
      [Jane] => 5342
      [Peter] => 5623
    )
    */
    ?>
    
    If you need to extract more than one column from an array, you can use array_intersect_key on each element, like so:
    function array_column_multi(array $input, array $column_keys) {
      $result = array();
      $column_keys = array_flip($column_keys);
      foreach($input as $key => $el) {
        $result[$key] = array_intersect_key($el, $column_keys);
      }
      return $result;
    }
    I added a little more functionality to the more popular answers here to support the $index_key parameter for PHP < 5.5
    <?php
    // for php < 5.5
    if (!function_exists('array_column')) {
      function array_column($input, $column_key, $index_key = null) {
        $arr = array_map(function($d) use ($column_key, $index_key) {
          if (!isset($d[$column_key])) {
            return null;
          }
          if ($index_key !== null) {
            return array($d[$index_key] => $d[$column_key]);
          }
          return $d[$column_key];
        }, $input);
        if ($index_key !== null) {
          $tmp = array();
          foreach ($arr as $ar) {
            $tmp[key($ar)] = current($ar);
          }
          $arr = $tmp;
        }
        return $arr;
      }
    }
    ?>
    
    Here's a neat little snippet for filtering a set of records based on a the value of a column:
    <?php
    function dictionaryFilterList(array $source, array $data, string $column) : array
    {
      $new   = array_column($data, $column);
      $keep   = array_diff($new, $source);
      return array_intersect_key($data, $keep);
     }
    // Usage:
    $users = [
      ['first_name' => 'Jed', 'last_name' => 'Lopez'],
      ['first_name' => 'Carlos', 'last_name' => 'Granados'],
      ['first_name' => 'Dirty', 'last_name' => 'Diana'],
      ['first_name' => 'John', 'last_name' => 'Williams'],
      ['first_name' => 'Betty', 'last_name' => 'Boop'],
      ['first_name' => 'Dan', 'last_name' => 'Daniels'],
      ['first_name' => 'Britt', 'last_name' => 'Anderson'],
      ['first_name' => 'Will', 'last_name' => 'Smith'],
      ['first_name' => 'Magic', 'last_name' => 'Johnson'],
    ];
    var_dump(dictionaryFilterList(['Dirty', 'Dan'], $users, 'first_name'));
    // Outputs:
    [
      ['first_name' => 'Jed', 'last_name' => 'Lopez'],
      ['first_name' => 'Carlos', 'last_name' => 'Granados'],
      ['first_name' => 'John', 'last_name' => 'Williams'],
      ['first_name' => 'Betty', 'last_name' => 'Boop'],
      ['first_name' => 'Britt', 'last_name' => 'Anderson'],
      ['first_name' => 'Will', 'last_name' => 'Smith'],
      ['first_name' => 'Magic', 'last_name' => 'Johnson']
    ]
    ?>
    
    //php < 5.5
    if(function_exists('array_column'))
    {
      function array_column($arr_data, $col)
      {
        $result = array_map(function($arr){return $arr[$col]}, $arr_data);
        return $result;
      }
    }
    if (!function_exists('array_column'))
    {
      function array_column($input, $column_key=null, $index_key=null)
      {
        $result = array();
        $i = 0;
        foreach ($input as $v)
        {
          $k = $index_key === null || !isset($v[$index_key]) ? $i++ : $v[$index_key];
          $result[$k] = $column_key === null ? $v : (isset($v[$column_key]) ? $v[$column_key] : null);
        }
        return $result;
      }
    }
    Note that this function will return the last entry when possible keys are duplicated.
    <?php
    $array = array(
      array(
        '1-1',
        'one',
        'one',
      ),
      array(
        '1-2',
        'two',
        'one',
      ),
    );
    var_dump(array_column($array, $value = 0, $index = 1));
    var_dump(array_column($array, $value = 0, $index = 2));
    // returns:
    /*
    array (size=2)
     'one' => string '1-1' (length=3)
     'two' => string '1-2' (length=3)
    array (size=1)
     'one' => string '1-2' (length=3)
    */
    ?>
    
    Please note this function accepts 2D-arrays ONLY, and silently returns empty array when non-array argument is provided.
    Code:
    class testObject {
      public $a = 123;
    }
    $testArray = [new testObject(), new testObject(), new testObject()];
    $result = array_column($testArray, 'a')); //array(0) { }
    a simple solution:
    function arrayColumn(array $array, $column_key, $index_key=null){
        if(function_exists('array_column ')){
          return array_column($array, $column_key, $index_key);
        }
        $result = [];
        foreach($array as $arr){
          if(!is_array($arr)) continue;
          if(is_null($column_key)){
            $value = $arr;
          }else{
            $value = $arr[$column_key];
          }
          if(!is_null($index_key)){
            $key = $arr[$index_key];
            $result[$key] = $value;
          }else{
            $result[] = $value;
          }
        }
        return $result;
      }
    If array_column is not available you can use the following function, which also has the $index_key parameter:
    if (!function_exists('array_column')) {
      function array_column($array, $column_key, $index_key = null) 
      {
        return array_reduce($array, function ($result, $item) use ($column_key, $index_key) 
        {
          if (null === $index_key) {
            $result[] = $item[$column_key];
          } else {
            $result[$item[$index_key]] = $item[$column_key];
          }
          return $result;
        }, []);
      }
    }
    Another option for older PHP versions (pre 5.5.0) is to use array_walk():
    <?php
    $array = array(
     array('some' => 'var', 'foo' => 'bar'),
     array('some' => 'var', 'foo' => 'bar'),
     array('some' => 'var', 'foo' => 'bar')
    );
    array_walk($array, function(&$value, $key, $return) {
     $value = $value[$return];
    }, 'foo');
    print_r($array);
    // Array
    // (
    //   [0] => bar
    //   [1] => bar
    //   [2] => bar
    // )
    ?>
    
    This didn't work for me recursively and needed to come up with a solution. 
    Here's my solution to the function:
    if ( ! function_exists( 'array_column_recursive' ) ) {
      /**
       * Returns the values recursively from columns of the input array, identified by
       * the $columnKey.
       *
       * Optionally, you may provide an $indexKey to index the values in the returned
       * array by the values from the $indexKey column in the input array.
       *
       * @param array $input   A multi-dimensional array (record set) from which to pull
       *             a column of values.
       * @param mixed $columnKey The column of values to return. This value may be the
       *             integer key of the column you wish to retrieve, or it
       *             may be the string key name for an associative array.
       * @param mixed $indexKey (Optional.) The column to use as the index/keys for
       *             the returned array. This value may be the integer key
       *             of the column, or it may be the string key name.
       *
       * @return array
       */
      function array_column_recursive( $input = NULL, $columnKey = NULL, $indexKey = NULL ) {
        // Using func_get_args() in order to check for proper number of
        // parameters and trigger errors exactly as the built-in array_column()
        // does in PHP 5.5.
        $argc  = func_num_args();
        $params = func_get_args();
        if ( $argc < 2 ) {
          trigger_error( "array_column_recursive() expects at least 2 parameters, {$argc} given", E_USER_WARNING );
          return NULL;
        }
        if ( ! is_array( $params[ 0 ] ) ) {
          // Because we call back to this function, check if call was made by self to
          // prevent debug/error output for recursiveness :)
          $callers = debug_backtrace();
          if ( $callers[ 1 ][ 'function' ] != 'array_column_recursive' ){
            trigger_error( 'array_column_recursive() expects parameter 1 to be array, ' . gettype( $params[ 0 ] ) . ' given', E_USER_WARNING );
          }
          return NULL;
        }
        if ( ! is_int( $params[ 1 ] )
           && ! is_float( $params[ 1 ] )
           && ! is_string( $params[ 1 ] )
           && $params[ 1 ] !== NULL
           && ! ( is_object( $params[ 1 ] ) && method_exists( $params[ 1 ], '__toString' ) )
        ) {
          trigger_error( 'array_column_recursive(): The column key should be either a string or an integer', E_USER_WARNING );
          return FALSE;
        }
        if ( isset( $params[ 2 ] )
           && ! is_int( $params[ 2 ] )
           && ! is_float( $params[ 2 ] )
           && ! is_string( $params[ 2 ] )
           && ! ( is_object( $params[ 2 ] ) && method_exists( $params[ 2 ], '__toString' ) )
        ) {
          trigger_error( 'array_column_recursive(): The index key should be either a string or an integer', E_USER_WARNING );
          return FALSE;
        }
        $paramsInput   = $params[ 0 ];
        $paramsColumnKey = ( $params[ 1 ] !== NULL ) ? (string) $params[ 1 ] : NULL;
        $paramsIndexKey = NULL;
        if ( isset( $params[ 2 ] ) ) {
          if ( is_float( $params[ 2 ] ) || is_int( $params[ 2 ] ) ) {
            $paramsIndexKey = (int) $params[ 2 ];
          } else {
            $paramsIndexKey = (string) $params[ 2 ];
          }
        }
        $resultArray = array();
        foreach ( $paramsInput as $row ) {
          $key  = $value = NULL;
          $keySet = $valueSet = FALSE;
          if ( $paramsIndexKey !== NULL && array_key_exists( $paramsIndexKey, $row ) ) {
            $keySet = TRUE;
            $key  = (string) $row[ $paramsIndexKey ];
          }
          if ( $paramsColumnKey === NULL ) {
            $valueSet = TRUE;
            $value  = $row;
          } elseif ( is_array( $row ) && array_key_exists( $paramsColumnKey, $row ) ) {
            $valueSet = TRUE;
            $value  = $row[ $paramsColumnKey ];
          }
          $possibleValue = array_column_recursive( $row, $paramsColumnKey, $paramsIndexKey );
          if ( $possibleValue ) {
            $resultArray = array_merge( $possibleValue, $resultArray );
          }
          if ( $valueSet ) {
            if ( $keySet ) {
              $resultArray[ $key ] = $value;
            } else {
              $resultArray[ ] = $value;
            }
          }
        }
        return $resultArray;
      }
    }
    Retrieve multiple columns from an array:
    $columns_wanted = array('foo','bar');
    $array = array('foo'=>1,'bar'=>2,'foobar'=>3);
    $filtered_array = array_intersect_key(array_fill_keys($columns_wanted,''));
    //filtered_array 
    // array('foo'=>1,'bar'=>2);
    Value for existing key in the resulting array is rewritten with new value if it exists in another source sub-array.
    Presented function is good when You want to flatten nested array base on only one column, but if You want to flatten whole array You can use this method:
    /**
       * Method that transforms nested array into the flat one in below showed way:
       * [
       *   [
       *     [0]=>'today',
       *   ],
       *   [
       *     [0]=>'is',
       *     [1]=>'very',
       *     [2]=>  [
       *           [0]=>'warm'
       *         ],
       *   ],
       * ]
       *
       * Into:
       *
       * ['today','is','very','warm']
       *
       * @param $input
       * @return array
       */
      private function transformNestedArrayToFlatArray($input)
      {
        $output_array = [];
        if (is_array($input)) {
          foreach ($input as $value) {
            if (is_array($value)) {
              $output_array = array_merge($output_array, $this->transformNestedArrayToFlatArray($value));
            } else {
              array_push($output_array, $value);
            }
          }
        } else {
          array_push($output_array, $input);
        }
        return $output_array;
      }
    <?php
    if (!function_exists('array_column')) {
      function array_column($input, $column_key, $index_key = NULL) {
        if (!is_array($input)) {
          trigger_error(__FUNCTION__ . '() expects parameter 1 to be array, ' . gettype($input) . ' given', E_USER_WARNING);
          return FALSE;
        }
        
        $ret = array();
        foreach ($input as $k => $v) {    
          $value = NULL;
          if ($column_key === NULL) {
            $value = $v;
          }
          else {
            $value = $v[$column_key];
          }
          
          if ($index_key === NULL || !isset($v[$index_key])) {
            $ret[] = $value;
          }
          else {
            $ret[$v[$index_key]] = $value;
          }  
        }
        
        return $ret;
      }
    }
    ?>
    

    上篇:array_chunk()

    下篇:array_combine()