我有一个可以包含多个项目的数组,例如:
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
etc
我需要以最快的方式重组此数组,以便它最多包含X个项目。因此,如果我说X是3,那么结果数组必须是:
Item 1 , Item 2
Item 3, Item 4
Item 5, Item 6
etc
或如果它有7个项目,那就是:
Item 1 , Item 2, Item 3,
Item 4, Item 5,
Item 6, Item 7
最简单的方法是什么?
我从这开始,但似乎真的必须有一个更简单的方法:
foreach ($addressParts as $part)
{
if (empty($part)) continue;
if (empty($addressLines[$count])) $addressLines[$count] = '';
$addressLines[$count] .= $part;
$count++;
if ($count > 2) $count = 0;
}
此外,这不起作用,因为你最终会得到这个:
item 1, item 4, item 7
item 2, item 5
item 3, item 6
......这是错的。有什么想法吗?
更新
如果我从:
开始Array
(
[0] => item 1
[1] => item 2
[2] => item 3
[3] => item 4
[4] => item 5
[5] => item 6
[6] => item 7
)
我想结束:
Array
(
[0] => item 1, item 2, item 3
[1] => item 4, item 5
[2] => item 6, item 7
)
有意义吗?
答案 0 :(得分:5)
此功能根据您的示例将元素组合到新数组中。它处理任意数量的输入元素。
function ReduceArray($input, $length) {
$frac = $length / count($input);
$frac = $frac + 0.0001; // Offset for float calculations
$index = 0.0;
// Copy the elements, rolling over on $index
$temp = array();
foreach ($input as $part) {
$i= floor($index);
if (!isset($temp[$i])) {
$temp[$i] = array($part);
} else {
$temp[$i][] = $part;
}
$index += $frac;
}
// Combine the sub arrays
$output = array();
foreach ($temp as $line) {
$output[] = implode(', ', $line);
}
return $output;
}
$input = array('Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7');
$output = ReduceArray($input, 3);
print_r($output);
输出
Array
(
[0] => Item 1, Item 2, Item 3
[1] => Item 4, Item 5
[2] => Item 6, Item 7
)
根据给定的输出编辑“修复”输出。
编辑参见注释九个元素,最多可测试12个元素。谢谢sectus
答案 1 :(得分:4)
对于每个组,计算第一个元素的偏移量和组长度,从输入数组中复制该切片。
function array_group_elements($array, $groups) {
$result = array();
$count = count($array);
// minimum in each group
$limit = floor($count / $groups);
// balance, modulo
$overhead = $count % $groups;
// for each group
for ($i = 0; $i < $groups; ++$i) {
// group offset, add 1 for each group that got a balance element
$offset = ($i * $limit) + ($i < $overhead ? $i : $overhead);
// length, add 1 if it is a group with balance element
$length = $limit + ($i < $overhead ? 1 : 0);
// copy slice from original array
$result[] = array_slice($array, $offset, $length);
}
return $result;
}
$input = array('Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7');
$grouped = array_group_elements($input, 3);
var_dump(
array_map(
function($group) {
return implode(', ', $group);
},
$grouped
)
);
输出:
array(3) {
[0]=>
string(22) "Item 1, Item 2, Item 3"
[1]=>
string(14) "Item 4, Item 5"
[2]=>
string(14) "Item 6, Item 7"
}
函数array_group_elements()遍历$ groups(3次),而不是$ array(7次)。
答案 2 :(得分:3)
我已经提出了以下算法,可以在每一行中保持正确数量的项目;在每次迭代中,我们将剩余行数与剩余项目的划分进行四舍五入:
$a = range(1,7);
$len = count($a);
$res = array();
$max = 3;
$i = 0;
while ($i < $len) {
// divide the remaining number of items by the maximum rows allowed
// this gives the width for the current row
$width = ceil(($len - $i) / $max);
$res[] = join(', ', array_slice($a, $i, $width));
// adjust pointer and reduce the maximum
$i += $width;
--$max;
}
print_r($res);
答案 3 :(得分:3)
我有两种不同方法的功能。
function restructureArray1($array, $x)
{
$size = sizeof($array);
if ($size < $x)
return array_chunk($array, 1) + array_fill(0, $x, array());
// chunk by 1 element and add missing empty elements
$big_row_length = (int) ($size / $x) + 1;
$big_rows_chunk = array_splice($array, 0, $size % $x * $big_row_length);
// $big_rows_chunk contains items with big rows
// $array now contains items with small rows
return array_merge(array_chunk($big_rows_chunk, $big_row_length), array_chunk($array, $big_row_length - 1));
// chunk and merge
}
function restructureArray2($array, $x)
{
$size = sizeof($array);
$small_row_length = (int) ($size / $x);
$big_row_count = $size % $x;
for ($i = 0; $i < $x; ++$i)
{
$length = $small_row_length + (int) ($i < $big_row_count); // type juggling
$return [] = array_splice($array, 0, $length);
// $return[] contains one row
// $array now contains rest of array
}
return $return;
}
要获得包含数组字符串的结果,只需要array_map。
$x = 3;
$size = 7;
$array = range(1, $size);
$result1 = restructureArray1($array, $x);
$result2 = restructureArray2($array, $x);
var_dump(array_map(function($array)
{ return implode(', ', $array); }, $result2));
文档的相关链接:array_splice,array_chunk,array_merge
P.S。 最短的解决方案
function restructureArray3($array, $x)
{
while($x)
$return [] = array_splice($array, 0, ceil(sizeof($array) / $x--));
return $return;
}
答案 4 :(得分:2)
<?php
$source_array = array(
'item 1',
'item 2',
'item 3',
'item 4',
'item 5',
'item 6',
'item 7',
'item 8',
'item 9',
'item 10',
);
$k = 4;
// allocating cells
$allocated_cells_sizes = array();
$ik = 0;
foreach ($source_array as $value){
if (! isset($allocated_cells_sizes[$ik])) $allocated_cells_sizes[$ik] = 0;
$allocated_cells_sizes[$ik] ++;
if (++$ik >= $k) $ik = 0;
}
// filling result array
$result = array();
foreach ($allocated_cells_sizes as $cells_sizes){
$result[] = implode(', ', array_slice($source_array, 0, $cells_sizes));
$source_array = array_slice($source_array, $cells_sizes, null);
}
print_r($result);
/**
* Output
* Array
(
[0] => item 1, item 2, item 3
[1] => item 4, item 5, item 6
[2] => item 7, item 8
[3] => item 9, item 10
)
*/
答案 5 :(得分:2)
对于每个组,您需要计算适合每个分段的最大项目数,因此我使用了ceil();功能总是向上舍入。
输入:
Array
(
[0] => item1
[1] => item2
[2] => item3
[3] => item4
[4] => item5
[5] => item6
[6] => item7
)
功能:
function segment_array($array, $segment = '3'){
// Count the items
$count = count($array);
// Create an array item for each segment
for($i=0;$i<$segment;$i++){
$offset += ($count - ($count - $chunk));
$chunk = ceil(($count - $offset)/($segment - $i));
$set[$i] = array_slice($array, $offset, $chunk);
$new_array[] = implode(', ', $set[$i]);
}
return($new_array);
}
$segmented = segment_array($array, '3');
输出:
Array
(
[0] => item1, item2, item3
[1] => item4, item5
[2] => item6, item7
)
答案 6 :(得分:2)
代码:
$input = array('Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7');
$height = 3;
$commonWidth = floor(count($input) / $height);
$remaining = count($input) % $height;
$i = 0;
for ($j = 0; $j < $height; $j++) {
$width = $commonWidth + (0 < $remaining--);
$output[] = implode(', ', array_slice($input, $i, $width));
$i += $width;
}
print_r($output);
输出:
Array
(
[0] => Item 1, Item 2, Item 3
[1] => Item 4, Item 5
[2] => Item 6, Item 7
)
我想知道问题描述是否不正确,并且所需的结果实际上是一个多维数组,而不是连接字符串数组。在这种情况下,只需删除对implode的调用:
$input = array('Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7');
$height = 3;
$commonWidth = floor(count($input) / $height);
$remaining = count($input) % $height;
$i = 0;
for ($j = 0; $j < $height; $j++) {
$width = $commonWidth + (0 < $remaining--);
$output[] = array_slice($input, $i, $width);
$i += $width;
}
print_r($output);
输出是:
Array
(
[0] => Array
(
[0] => Item 1
[1] => Item 2
[2] => Item 3
)
[1] => Array
(
[0] => Item 4
[1] => Item 5
)
[2] => Array
(
[0] => Item 6
[1] => Item 7
)
)
答案 7 :(得分:1)
为任意数量的物品工作。并更改任意数量的列,只需更改$ x值。
<?php
$arr = array('Item 1','Item 2','Item 3','Item 4','Item 5','Item 6', 'Item 7');
$x = 3;
$newArr = array();
$j = 0;
foreach($arr as $key=>$val){
if($j == $x){
$j = 0;
}
$newArr[$j][] = $val;
$j++;
}
foreach($newArr as $key=>$val){
$tempVal = implode(',', $val);
$newArr[$key] = $tempVal;
}
print_r($newArr);
?>
答案 8 :(得分:1)
如果你对二维数组感到满意,如果最后一行比其他所有数组都小,你会感到高兴,这里有一个单行:
function split_array1($orig_array, $parts = 1) {
return array_chunk($orig_array,ceil(count($orig_array)/$parts));
}
同样的事情,将每个部分合并为字符串:
function split_array2($orig_array, $parts = 1) {
$split = array_chunk($orig_array,ceil(count($orig_array)/$parts));
foreach ($split as &$row) $row = join($row, ', ');
return $split;
}
输出三项测试,包括7项,8项和9项:
Array ( [0] => Item 1, Item 2, Item 3 [1] => Item 4, Item 5, Item 6 [2] => Item 7 )
Array ( [0] => Item 1, Item 2, Item 3 [1] => Item 4, Item 5, Item 6 [2] => Item 7, Item 8 )
Array ( [0] => Item 1, Item 2, Item 3 [1] => Item 4, Item 5, Item 6 [2] => Item 7, Item 8, Item 9 )
测试:
$input = array('Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7', 'Item 8', 'Item 9');
for ($size=7; $size<=count($input); $size++){
$output = split_array2(array_slice($input, 0, $size), 3);
print_r($output);
echo '<br>';
}
这将完全符合您的示例:
function split_array3($orig_array, $parts = 1) {
$count = count($orig_array);
for ($i=0, $index=0; $i<$parts; $i++) {
$size_of_sub = ceil(($count - $index) / ($parts-$i));
$split[$i] = join(array_slice($orig_array, $index, $size_of_sub), ', ');
$index += $size_of_sub;
}
return $split;
}
结果:
Array ( [0] => Item 1, Item 2, Item 3 [1] => Item 4, Item 5 [2] => Item 6, Item 7 )
Array ( [0] => Item 1, Item 2, Item 3 [1] => Item 4, Item 5, Item 6 [2] => Item 7, Item 8 )
Array ( [0] => Item 1, Item 2, Item 3 [1] => Item 4, Item 5, Item 6 [2] => Item 7, Item 8, Item 9 )
只是为了好玩,这是一个使用递归的解决方案:
function recursive_split_array($orig_array, $num_sub_arrays = 1) {
$size_of_sub = ceil(count($orig_array) / $num_sub_arrays);
$split[0] = join(array_slice($orig_array, 0, $size_of_sub),', ');
$split = array_merge( $split,
split_array(array_slice($orig_array, $size_of_sub,
count($orig_array)-$size_of_sub),$num_sub_arrays - 1));
return $split;
}
答案 9 :(得分:1)
另一种算法,因为据我所知,问题在于重组数组,因此在没有创建临时数组时可以实现最佳效率。
<?php
function group_array(&$array, $parts = 3)
{
$size = count($array);
$length = floor($size / $parts);
$remains = $size % $parts;
$done = 0;
for($i = 0; $i < $parts; ++$i)
{
$real_length = $length + ($i < $remains ? 1 : 0);
$array[$i] = $array[$done];
for($j = $done + 1; $j < min($done + $real_length, $size); ++$j)
$array[$i] .= ', ' . $array[$j];
$done += $real_length;
}
for($i = $size; $i >= $parts ; --$i)
unset($array[$i]);
}
?>
测试案例#1:
<?php
$array = array("item 1", "item 2", "item 3", "item 4", "item 5", "item 6", "item 7");
group_array($array);
echo '<pre>' . print_r($array, true) . '</pre>';
?>
输出:
Array
(
[0] => item 1, item 2, item 3
[1] => item 4, item 5
[2] => item 6, item 7
)
测试案例#2:
<?php
$array = array("item 1", "item 2", "item 3", "item 4", "item 5", "item 6",
"item 7", "item 8", "item 9", "item 10");
group_array($array);
echo '<pre>' . print_r($array, true) . '</pre>';
?>
输出:
Array
(
[0] => item 1, item 2, item 3, item 4
[1] => item 5, item 6, item 7
[2] => item 8, item 9, item 10
)
答案 10 :(得分:0)
这里是an answer of mine on another very, very similar question的改编版(几乎重复)。
代码:(Demo)
function custom_chunk($array, $maxrows) {
$result = [];
$size = sizeof($array);
$columns = ceil($size / $maxrows);
$fullrows = $size - ($columns - 1) * $maxrows;
for ($i = 0; $i < $maxrows; ++$i) {
$result[] = implode(', ', array_splice($array, 0, ($i < $fullrows ? $columns : $columns - 1)));
}
return $result;
}
$data = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7'];
var_export(custom_chunk($data, 3));
输出:
array (
0 => 'Item 1, Item 2, Item 3',
1 => 'Item 4, Item 5',
2 => 'Item 6, Item 7',
)
答案 11 :(得分:0)
很抱歉这应该是评论但我不能发表评论可能是因为我的声誉......
如果你有一个包含7个元素的数组,你知道你将数组除以3还是你必须找到除数?
编辑1 像这样的东西? :
$formatedAddress = array();
$divisor = 3;
$key = 0;
$counter =1;
foreach ($addressParts as $part)
{
if(!empty($part){
$formattedAddress[$key] = $part;
if($counter != $divisor){
$counter++;
}else{
$counter = 1;
$key++;
}
}
}
编辑2:
我发现了一些错误:
$formatedAddress = array();
$divisor = 3;
$key = 0;
$counter =1;
foreach ($addressParts as $part)
{
if(!empty($part)){
$formatedAddress[$key][] = $part;
if($counter != $divisor){
$counter++;
}else{
$counter = 1;
$key++;
}
}
}
答案 12 :(得分:0)
这看起来非常简洁:
function ReduceArray($input,$length)
{
$count = count($input);
// fill new array with new number of empty elements
$newArray = array_fill(0,ceil($count/$length),"");
for( $i = $count; $i > 0; $i--)
{
// calculate index in new array to insert item
$index = ceil($i / $length)-1;
// we need a comma separator in this position if the array is empty
$sep = ($newArray[$index] != "" ? "," : "");
// insert into new array
$newArray[$index] = array_pop($input) . $sep . $newArray[$index] ;
}
return $newArray;
}
答案 13 :(得分:0)
可以吗?
$items = array('item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7');
array_unshift($items, '');
$chunkitems = array_chunk($items, 2);
$newitems = array_map(function($v){return implode(', ', $v);}, $chunkitems);
$first = ltrim(implode(', ', array(array_shift($newitems), array_shift($newitems))),', ');
array_unshift($newitems, $first);
print_r($newitems);
答案 14 :(得分:0)
试试这个:
function array_group($array, $X){
$extra = count($array)%$X;
$pre = array_splice($array, 0, $extra);
$post = array_chunk($array, count($array)/$X);
$post[0] = array_merge($pre, $post[0]);
foreach ($post as &$key) {
$key = implode(', ', $key);
}
return $post;
}
答案 15 :(得分:0)
<?php
$sample_array = array('item 1','item 2', 'itme 3','item 4', 'item 5','item 6','item 7', 'item 8','item 9','item 10',
'item 11','item 12','item 13','item 14','item 15','item 16');
restructure($sample_array,3);
function restructure($array ,$size)
{
$i=0;
while($i<= count($array))
{
$j=$i;
$count = 0;
while ($count<$size)
{
if($j<count($array))
{
echo $array[$j]. " ";
$j++;
}
$count++;
}
echo '<br>';
$i=$i+$size;
}
}
?>
<?php
答案 16 :(得分:0)
$source_array = array(
'item 1',
'item 2',
'item 3',
'item 4',
'item 5',
'item 6',
'item 7',
'item 8',
'item 9',
'item 10',
);
function reduce_array($input, $first_count = 3, $count = 2)
{
$array_slice = array(array_slice($input, 0, $first_count));
$array_chunk = array_chunk(array_slice($input, $first_count), $count);
return array_merge($array_slice, $array_chunk);
}
$reduce_array = reduce_array($source_array);
var_dump($reduce_array);
foreach($reduce_array as $array)
{
var_dump(implode(',', $array));
}
Output:
array(5) {
[0]=>
array(3) {
[0]=>
string(6) "item 1"
[1]=>
string(6) "item 2"
[2]=>
string(6) "item 3"
}
[1]=>
array(2) {
[0]=>
string(6) "item 4"
[1]=>
string(6) "item 5"
}
[2]=>
array(2) {
[0]=>
string(6) "item 6"
[1]=>
string(6) "item 7"
}
[3]=>
array(2) {
[0]=>
string(6) "item 8"
[1]=>
string(6) "item 9"
}
[4]=>
array(1) {
[0]=>
string(7) "item 10"
}
}
string(20) "item 1,item 2,item 3"
string(13) "item 4,item 5"
string(13) "item 6,item 7"
string(13) "item 8,item 9"
string(7) "item 10"
答案 17 :(得分:-1)
另外一分钱,也许吧。 : - )
<?php
function restructure($x,$slots)
{
$result=array();
$count=count($x);
$least=(int)($count/$slots);
$excess=$count-$least*$slots;
for($i=0;$i<$slots*$excess;$i+=$least+1)
array_push($result,implode(", ",array_slice($x,$i,$least+1)));
for(;$i<$count;$i+=$least)
array_push($result,implode(", ",array_slice($x,$i,$least)));
return $result;
}
if (PHP_SAPI==='cli') {
$x=array(
"item 1",
"item 2",
"item 3",
"item 4",
"item 5",
"item 6",
"item 7",
);
print_r(restructure($x,3));
}
这使得:
Array
(
[0] => item 1, item 2, item 3
[1] => item 4, item 5
[2] => item 6, item 7
)
答案 18 :(得分:-1)
很棒的问题+1。我已经更加动态地创建了解决方案。
这将是另一个相应改变事物的优势:
<?
//can n number of array items
$items = array('item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7');
//counting of total number of items
$total_items = count($items);
//item to find in array
$find_item = "item7";
//first item found key number
$key = array_search($find_item, $items);
//Splitting into two
//array with last found as item
$temp_output1 = array_slice($items, 0, $key+1);
//items left
$temp_output2 = array_slice($items, $key+1, $total_items);
//minimum number items to group
$minimum_group=2;
//Maximum Number of Grouped items
$maximum_group=4;
if ( $temp_output1 ) {
//sending to group accordingly
$output1 = do_slicing($temp_output1, $minimum_group, $maximum_group);
print_r($output1);
}
if ( $temp_output2 ) {
//sending to group accordingly
$output2 = do_slicing($temp_output2, $minimum_group, $maximum_group);
print_r($output2);
}
function do_slicing($temp_output = array(), $minimum_group, $maximum_group){
$count = count($temp_output);
//array is equal to min grouping
if ( $count == $minimum_group){
//Group them and return
return by_grouping($temp_output, $minimum_group);
}elseif ($count == $maximum_group){
//if items equal to maximum then group them and return
return by_grouping($temp_output, $maximum_group);
}elseif ( ($count > $minimum_group) and ($count < $maximum_group)){
return by_grouping($temp_output, count($temp_output));
}elseif ($count == 1) {
//if item is 1 print error or return from here
return $temp_output;
}else{
//calculate the total number of groups available
$item_slice_count = intval($count/$maximum_group);
//Split them as grouped members
$temp_slice = array_slice($temp_output, 0,
($item_slice_count*$maximum_group));
//non group members
$temp_slice2 = array_slice($temp_output,
($item_slice_count*$maximum_group), $count);
//if there is no non group members
if ( !$temp_slice2 ) {
//combine them and return according to maximum grouping
return by_grouping($temp_slice, $maximum_group);
}else{
if (
(count($temp_slice2) === $minimum_group) or
(
(count($temp_slice2) > $minimum_group) and
(count($temp_slice2) <
$maximum_group)
)
){
//if count of slice2 equal to minimum group then
$a=by_grouping($temp_slice, $maximum_group);
if (
(count($temp_slice2) > $minimum_group) and
(count($temp_slice2) <
$maximum_group)
){
$b=by_grouping($temp_slice2, count($temp_slice2));
}else{
$b=by_grouping($temp_slice2, $minimum_group);
}
return array_merge($a, $b);
}elseif( count($temp_slice2) < $minimum_group ) {
//if less then minimum group then
//if total count is divisible with minimum group
if ( ($count % $minimum_group ) == 0 ){
//return after clubbing according minimum group
return by_grouping($temp_output, $minimum_group);
}else{
//Where last group is not equal to minimum group
//Minimum more needed to complete last slice
$minimum_needed = $minimum_group - count($temp_slice2);
//slice1 become
$slice1 = array_slice($temp_output, 0, (
($item_slice_count-1)*$maximum_group));
//slice2 would be
$slice2 = array_slice($temp_output, (
($item_slice_count-1)*$maximum_group),
($maximum_group-$minimum_needed));
//slice 3 then
$slice3 = array_slice($temp_output, (
(($item_slice_count-1)*$maximum_group) +
($maximum_group-$minimum_needed)),
$count);
//if slice2 is greater or equal to minimum group then
if ( $slice2>=$minimum_group) {
$a=by_grouping($slice1, $maximum_group);
$b=array_merge($a, by_grouping($slice2,
count($slice2)));
$c=by_grouping($slice3, $minimum_group);
return array_merge($b, $c);
}else{
die("This Situation doesn't reached any time");
}
}
}
}
}
}
//Grouping of members according to slices provided
function by_grouping($temp_slice, $group){
$return = array();
$temp = array_chunk($temp_slice, $group);
foreach($temp as $a){
$return[] = implode(', ', $a);
}
return $return;
}
?>