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 ) )
参见
array_slice()
从数组中取出一段
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; } ?>