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

    (PHP 4 >= 4.2.0, PHP 5, PHP 7)

    将一个数组分割成多个

    说明

    array_chunk(array $array,int $size[,bool $preserve_keys= false]): array

    将一个数组分割成多个数组,其中每个数组的单元数目由$size决定。最后一个数组的单元数目可能会少于$size个。

    参数

    $array

    需要操作的数组

    $size

    每个数组的单元数目

    $preserve_keys

    设为TRUE,可以使 PHP 保留输入数组中原来的键名。如果你指定了FALSE,那每个结果数组将用从零开始的新数字索引。默认值是FALSE

    返回值

    得到的数组是一个多维数组中的单元,其索引从零开始,每一维包含了$size个元素。

    错误/异常

    如果$size小于 1,会抛出一个E_WARNING错误并返回NULL

    范例

    Example #1array_chunk()例子

    <?php
    $input_array = array('a', 'b', 'c', 'd', 'e');
    print_r(array_chunk($input_array, 2));
    print_r(array_chunk($input_array, 2, true));
    ?>
    

    以上例程会输出:

    Array
    (
        [0] => Array
            (
                [0] => a
                [1] => b
            )
        [1] => Array
            (
                [0] => c
                [1] => d
            )
        [2] => Array
            (
                [0] => e
            )
    )
    Array
    (
        [0] => Array
            (
                [0] => a
                [1] => b
            )
        [1] => Array
            (
                [2] => c
                [3] => d
            )
        [2] => Array
            (
                [4] => e
            )
    )
    

    参见

    Tried to use an example below (#56022) for array_chunk_fixed that would "partition" or divide an array into a desired number of split lists -- a useful procedure for "chunking" up objects or text items into columns, or partitioning any type of data resource. However, there seems to be a flaw with array_chunk_fixed — for instance, try it with a nine item list and with four partitions. It results in 3 entries with 3 items, then a blank array.
    So, here is the output of my own dabbling on the matter:
    <?php
    function partition( $list, $p ) {
      $listlen = count( $list );
      $partlen = floor( $listlen / $p );
      $partrem = $listlen % $p;
      $partition = array();
      $mark = 0;
      for ($px = 0; $px < $p; $px++) {
        $incr = ($px < $partrem) ? $partlen + 1 : $partlen;
        $partition[$px] = array_slice( $list, $mark, $incr );
        $mark += $incr;
      }
      return $partition;
    }
    $citylist = array( "Black Canyon City", "Chandler", "Flagstaff", "Gilbert", "Glendale", "Globe", "Mesa", "Miami",
              "Phoenix", "Peoria", "Prescott", "Scottsdale", "Sun City", "Surprise", "Tempe", "Tucson", "Wickenburg" );
    print_r( partition( $citylist, 3 ) );
    ?>
    Array
    (
      [0] => Array
        (
          [0] => Black Canyon City
          [1] => Chandler
          [2] => Flagstaff
          [3] => Gilbert
          [4] => Glendale
          [5] => Globe
        )
      [1] => Array
        (
          [0] => Mesa
          [1] => Miami
          [2] => Phoenix
          [3] => Peoria
          [4] => Prescott
          [5] => Scottsdale
        )
      [2] => Array
        (
          [0] => Sun City
          [1] => Surprise
          [2] => Tempe
          [3] => Tucson
          [4] => Wickenburg
        )
    )
    Here my array_chunk_values( ) with values distributed by lines (columns are balanced as much as possible) :
    <?php
      function array_chunk_vertical($data, $columns) {
        $n = count($data) ;
        $per_column = floor($n / $columns) ;
        $rest = $n % $columns ;
        // The map
        $per_columns = array( ) ;
        for ( $i = 0 ; $i < $columns ; $i++ ) {
          $per_columns[$i] = $per_column + ($i < $rest ? 1 : 0) ;
        }
        $tabular = array( ) ;
        foreach ( $per_columns as $rows ) {
          for ( $i = 0 ; $i < $rows ; $i++ ) {
            $tabular[$i][ ] = array_shift($data) ;
          }
        }
        return $tabular ;
      }
      header('Content-Type: text/plain') ;
      $data = array_chunk_vertical(range(1, 31), 7) ;
      foreach ( $data as $row ) {
        foreach ( $row as $value ) {
          printf('[%2s]', $value) ;
        }
        echo "\r\n" ;
      }
      /*
        Output :
        [ 1][ 6][11][16][20][24][28]
        [ 2][ 7][12][17][21][25][29]
        [ 3][ 8][13][18][22][26][30]
        [ 4][ 9][14][19][23][27][31]
        [ 5][10][15]
      */
    ?>
    
    chunk array vertically
    $arr  = range(1, 19);
    function array_chunk_vertical($arr, $percolnum){
      $n = count($arr);
      $mod  = $n % $percolnum;
      $cols  = floor($n / $percolnum);
      $mod ? $cols++ : null ;
      $re   = array();
      for($col = 0; $col < $cols; $col++){
        for($row = 0; $row < $percolnum; $row++){
          if($arr){
            $re[$row][]  = array_shift($arr);
          }
        }
      }
      return $re;
    }
    $result = array_chunk_vertical($arr, 6);
    foreach($result as $row){
      foreach($row as $val){
        echo '['.$val.']';
      }
      echo '<br/>';
    }
    /*
    [1][7][13][19]
    [2][8][14]
    [3][9][15]
    [4][10][16]
    [5][11][17]
    [6][12][18]
     */
    Response to azspot at gmail dot com function partition.
    $columns = 3;
    $citylist = array('Black Canyon City', 'Chandler', 'Flagstaff', 'Gilbert', 'Glendale', 'Globe', 'Mesa', 'Miami', 'Phoenix', 'Peoria', 'Prescott', 'Scottsdale', 'Sun City', 'Surprise', 'Tempe', 'Tucson', 'Wickenburg');
    print_r(array_chunk($citylist, ceil(count($citylist) / $columns)));
    Output:
    Array
    (
      [0] => Array
        (
          [0] => Black Canyon City
          [1] => Chandler
          [2] => Flagstaff
          [3] => Gilbert
          [4] => Glendale
          [5] => Globe
        )
      [1] => Array
        (
          [0] => Mesa
          [1] => Miami
          [2] => Phoenix
          [3] => Peoria
          [4] => Prescott
          [5] => Scottsdale
        )
      [2] => Array
        (
          [0] => Sun City
          [1] => Surprise
          [2] => Tempe
          [3] => Tucson
          [4] => Wickenburg
        )
    )
    If you just want to grab one chunk from an array, you should use array_slice().
    To reverse an array_chunk, use array_merge, passing the chunks as a variadic:
    <?php
    $array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    $chunks = array_chunk($array, 3);
    // $chunks = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    $de_chunked = array_merge(…$chunks);
    // $de_chunked = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    ?>
    
    This function takes each few elements of an array and averages them together. It then places the averages in a new array. It is used to smooth out data. For example lets say you have a years worth of hit data to a site and you want to graph it by the week. Then use a bucket of 7 and graph the functions output.
    function array_bucket($array, $bucket_size) // bucket filter
    {
      if (!is_array($array)) return false; // no empty arrays
      $buckets=array_chunk($array,$bucket_size); // chop up array into bucket size units
      foreach ($buckets as $bucket) $new_array[key($buckets])=array_sum($bucket)/count($bucket);
      return $new_array; // return new smooth array
    }
    array_chunk() is helpful when constructing tables with a known number of columns but an unknown number of values, such as a calendar month. Example:
    <?php
    $values = range(1, 31);
    $rows = array_chunk($values, 7);
    print "<table>\n";
    foreach ($rows as $row) {
      print "<tr>\n";
      foreach ($row as $value) {
        print "<td>" . $value . "</td>\n";
      }
      print "</tr>\n";
    }
    print "</table>\n";
    ?>
    Outputs:
    1 2 3 4 5 6 7 
    8 9 10 11 12 13 14 
    15 16 17 18 19 20 21 
    22 23 24 25 26 27 28 
    29 30 31 
    The other direction is possible too, with the aid of a function included at the bottom of this note. Changing this line:
     $rows = array_chunk($values, 7);
    To this:
     $rows = array_chunk_vertical($values, 7);
    Produces a vertical calendar with seven columns:
    1 6 11 16 21 26 31 
    2 7 12 17 22 27 
    3 8 13 18 23 28 
    4 9 14 19 24 29 
    5 10 15 20 25 30 
    You can also specify that $size refers to the number of rows, not columns:
     $rows = array_chunk_vertical($values, 7, false, false);
    Producing this:
    1 8 15 22 29 
    2 9 16 23 30 
    3 10 17 24 31 
    4 11 18 25 
    5 12 19 26 
    6 13 20 27 
    7 14 21 28 
    The function:
    <?php
    function array_chunk_vertical($input, $size, $preserve_keys = false, $size_is_horizontal = true)
    {
      $chunks = array();
      
      if ($size_is_horizontal) {
        $chunk_count = ceil(count($input) / $size);
      } else {
        $chunk_count = $size;
      }
      
      for ($chunk_index = 0; $chunk_index < $chunk_count; $chunk_index++) {
        $chunks[] = array();
      }
      $chunk_index = 0;
      foreach ($input as $key => $value)
      {
        if ($preserve_keys) {
          $chunks[$chunk_index][$key] = $value;
        } else {
          $chunks[$chunk_index][] = $value;
        }
        
        if (++$chunk_index == $chunk_count) {
          $chunk_index = 0;
        }
      }
      
      return $chunks;
    }
    ?>
    
    [Editors note: This function was based on a previous function by gphemsley at nospam users dot sourceforge.net]
    For those of you that need array_chunk() for PHP < 4.2.0, this function should do the trick:
    <?php
    if (!function_exists('array_chunk')) {
      function array_chunk( $input, $size, $preserve_keys = false) {
        @reset( $input );
        
        $i = $j = 0;
        while( @list( $key, $value ) = @each( $input ) ) {
          if( !( isset( $chunks[$i] ) ) ) {
            $chunks[$i] = array();
          }
          if( count( $chunks[$i] ) < $size ) {
            if( $preserve_keys ) {
              $chunks[$i][$key] = $value;
              $j++;
            } else {
              $chunks[$i][] = $value;
            }
          } else {
            $i++;
            if( $preserve_keys ) {
              $chunks[$i][$key] = $value;
              $j++;
            } else {
              $j = 0;
              $chunks[$i][$j] = $value;
            }
          }
        }
        return $chunks;
      }
    }
    ?>
    
    based on the same syntax, useful about making columns :
    <?php
    function array_chunk_fixed($input, $num, $preserve_keys = FALSE) {
      $count = count($input) ;
      if($count)
        $input = array_chunk($input, ceil($count/$num), $preserve_keys) ;
      $input = array_pad($input, $num, array()) ;
      return $input ;
    }
    $array = array(1, 2, 3, 4, 5) ;
    print_r(array_chunk($array, 2)) ;
    print_r(array_chunk_fixed($array, 2)) ;
    ?>
    ---- array_chunk : fixed number of sub-items ----
    Array(
      [0] => Array(
          [0] => 1
          [1] => 2
        )
      [1] => Array(
          [0] => 3
          [1] => 4
        )
      [2] => Array(
          [0] => 5
        )
    )
    ---- array_chunk : fixed number of columns ----
    Array(
      [0] => Array(
          [0] => 1
          [1] => 2
          [2] => 3
        )
      [1] => Array(
          [0] => 4
          [1] => 5
        )
    )
    Hi, I've made a function to split an array into chunks based on columns wanted. For example:
    <?php $a = array(1,2,3,4,5,6,7,8); ?>
    goal (say, for 3 columns):
    <?php
    array(
      array(1,2,3),
      array(4,5,6),
      array(7,8)
    );
    ?>
    <?php
    function get_array_columns($array, $columns){
        
        $columns_map = array();
        for($i=0; $i<$columns; $i++){ $columns_map[] = 0; }//init columns
        
        //create map
        $count = count($array);
        $position = 0;
        while($count > 0){
          $columns_map[$position]++;
          $position = ($position < $columns-1) ? ++$position : 0;
          $count--;
        }
        //chunk the array based on map
        $chunked = array();
        foreach($columns_map as $map){
          $chunked[] = array_splice($array,0,$map);
        }
        
        return $chunked;
      }//end get_array_columns
    ?>
    
    This function can be used to reverse effect of <?php array_Chunk()?>.
    <?php
    function array_Unchunk($array)
    {
      return call_User_Func_Array('array_Merge',$array);
    }
    header('Content-Type: text/plain');
    $array=array(
      array(
          'Black Canyon City',
          'Chandler',
          'Flagstaff',
          'Gilbert',
          'Glendale',
          'Globe',
      ),
      array(
          'Mesa',
          'Miami',
          'Phoenix',
          'Peoria',
          'Prescott',
          'Scottsdale',
      ),
      array(
          'Sun City',
          'Surprise',
          'Tempe',
          'Tucson',
          'Wickenburg',
      ),
    );
    var_Dump(array_Unchunk($array));
    ?>
    Output:
    array(17) {
     [0]=>
     string(17) "Black Canyon City"
     [1]=>
     string(8) "Chandler"
     [2]=>
     string(9) "Flagstaff"
     [3]=>
     string(7) "Gilbert"
     [4]=>
     string(8) "Glendale"
     [5]=>
     string(5) "Globe"
     [6]=>
     string(4) "Mesa"
     [7]=>
     string(5) "Miami"
     [8]=>
     string(7) "Phoenix"
     [9]=>
     string(6) "Peoria"
     [10]=>
     string(8) "Prescott"
     [11]=>
     string(10) "Scottsdale"
     [12]=>
     string(8) "Sun City"
     [13]=>
     string(8) "Surprise"
     [14]=>
     string(5) "Tempe"
     [15]=>
     string(6) "Tucson"
     [16]=>
     string(10) "Wickenburg"
    }
    A breakdown by groups with excess:
    function array_chunk_greedy($arr, $count){
      $arr = array_chunk($arr, $count);
      if(($k = count($arr)-1) > 0){  
        if(count($arr[$k]) < $count){
          $arr[$k-1] = array_merge($arr[$k-1], $arr[$k]);
          unset($arr[$k]);
        }      
      }
      return $arr;  
    }
    $arr = range(1, 13);
    $arr = array_chunk_greedy($arr, 4);
    print_r($arr);
    [1,2,3,4,5,6,7,8,9,10,11,12,13] —> [1,2,3,4] [5,6,7,8] [9,10,11,12,13]
    More examples:
    [1,2,3,4,5,6,7,8,9,10,11,12] —> [1,2,3,4] [5,6,7,8] [9,10,11,12]
    [1,2,3,4,5,6,7,8,9,10,11,12,13] —> [1,2,3,4] [5,6,7,8] [9,10,11,12,13]
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14] —> [1,2,3,4] [5,6,7,8] [9,10,11,12,13,14]
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] —> [1,2,3,4] [5,6,7,8] [9,10,11,12,13,14,15]
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] —> [1,2,3,4] [5,6,7,8] [9,10,11,12] [13,14,15,16]
    Example report:
    $arr = range(1, 45);
    $arr = array_chunk_lazy($arr, 10);
    $arr = array_map(function($sub_value) {
          return implode('<br>', $sub_value);
        }, $arr);
    $title = '<h2>title</h2>';
    $arr = $title.implode($title, $arr).$title;
    echo $arr;
    Had need to chunk an object which implemented ArrayAccess Iterator Countable. array_chunk wouldn't do it. Should work for any list of things
    <?php
      $listOfThings = array(1,2,3,4,5,6,7,8,9,10,11,12,13);
      print_r(chunk_iterable($listOfThings, 4);
     function chunk_iterable($listOfThings, $size) {
       $chunk = 0;
       $chunks = array_fill(0, ceil(count($listOfThings) / $size) - 1, array());
       $index = 0;
       foreach($listOfThings as $thing) {
        if ($index && $index % $size == 0) $chunk++;
        $chunks[$chunk][] = $thing;
        $index++;
       }
       return $chunks;
     }
    ?>
    
    <table>
    <tr>
    <?php
    $array_chunkdata = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25);
    $chunk = array_chunk($array_chunkdata,5);
    $rev_counter = 2;
    function for_chunk($chunk_data){
      echo "<td><table>";
       foreach($chunk_data as $key => $chunk_value)
       {
        echo "<tr><td>";
        echo $chunk_value;
        echo "</td></tr>";
       }
       echo "</table></td>";  
    }
    foreach($chunk as $key => $chunk_data)
    {
      if($rev_counter%2==0)
      {  
       for_chunk($chunk_data);
      }
      else
      {
       $chunk_data = array_reverse($chunk_data);
       
       for_chunk($chunk_data);
       
      } 
     $rev_counter++;
    }
    ?> 
    </tr>
    </table>
    /*
    Output:
    1
    2
    3
    4
    5
      
    10
    9
    8
    7
    6
      
    11
    12
    13
    14
    15
      
    20
    19
    18
    17
    16
      
    21
    22
    23
    24
    25
    */
    Mistake key did not do what I thought. A patch.
    function array_bucket($array,$bucket_size)// bucket filter
    {
      if (!is_array($array)) return false;
      $buckets=array_chunk($array,$bucket_size);// chop up array into bucket size units
      $I=0;
      foreach ($buckets as $bucket)
      {
        $new_array[$I++]=array_sum($bucket)/count($bucket);
      }
      return $new_array;// return new array
    }
    Unfortunately, this function only accepts real arrays, not iterable objects... For that, you need this function:
    <?php
    function break_array($array, $page_size) {
     
     $arrays = array();
     $i = 0;
     
     foreach ($array as $index => $item) {
      if ($i++ % $page_size == 0) {
       $arrays[] = array();
       $current = & $arrays[count($arrays)-1];
      }
      $current[] = $item;
     }
     
     return $arrays;
     
    }
    ?>
    
    Couldn't get the array_chunk_values() working, so ended up with this implementation:
    <?php
    function array_chunk_columns($data, $num_columns) {
     $n = count($data);
     $per_column = floor($n / $num_columns);
     $rest = $n % $num_columns;
     $columns = array();
     $index = 0;
     for ($i = 0; $i < $num_columns; $i++) {
      // Add an extra item to each column while the column number is less than the
      // remainder.
      $add_rest = ($rest && ($i < $rest)) ? 1 : 0;
      $number = $per_column + $add_rest;
      $columns[] = array_slice($data, $index, $number);
      $index += $number;
     }
     return $columns;
    }
    ?>