我有一个数组,里面可以包含多个项目,例如:
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
)
有意义?
此函数根据您的示例将元素组合到一个新数组中。它处理任意数量的输入元素。
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
)
根据给定的输出编辑"固定"输出。
编辑 请参阅注释 对于 9 个元素,最多针对 12 个元素进行了测试。谢谢教派
对于每个组,计算第一个元素和组长度的偏移量,从输入数组中复制该切片。
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 次)。
我有两个不同方法的函数。
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
附言最短的解决方案
function restructureArray3($array, $x)
{
while($x)
$return [] = array_splice($array, 0, ceil(sizeof($array) / $x--));
return $return;
}
演示
我想出了以下算法,该算法可以在每行中保持拟合正确数量的项目; 在每次迭代中,我们将剩余行数与剩余项的划分四舍五入:
$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);
演示
<?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
)
*/
对于每个组,您需要计算每个段中适合的最大项目数,因此我使用 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
)
代码:
$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
)
我想知道问题描述是否不正确,所需的结果实际上是一个多维数组,而不是串联字符串的数组。在这种情况下,只需删除对内爆的调用:
$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
)
)
适用于任意数量的项目。 并更改任意数量的列,只需更改$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);
?>
另一种算法,因为据我了解,问题是就地重构数组,因此在不创建临时数组时可以实现最佳效率。
<?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
)
如果您对二维数组感到满意,并且很高兴最后一行可以比其他所有行为小得多,这里有一行:
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;
}
对不起,这应该是一个评论,但我不能做评论,也许是因为我的声誉......
当你有一个包含 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++;
}
}
}
$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"
试试这个:
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;
}
这似乎很简洁:
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;
}
吗?
$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);
<?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
另一个非常非常相似的问题(几乎重复)的回答的改编。
代码:(演示)
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',
)
很好的问题 +1 对它。我已经更动态地创建了解决方案。
- 由于用户输入可以是 1 中的任何数字.....n
- 要描述或更改的成员的最小分组
- 要描述或可以随时更改的最大成员分组
这将是对其他人进行相应更改的优势:
<?
//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;
}
?>
演示代码
也许还有一分钱。
<?php
function restructure($x,$slots)
{
$result=array();
$count=count($x);
$least=(int)($count/$slots);
$excess=$count-$least*$slots;
for($i=0;$i<($least+1)*$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
)
编辑:修复了@mickmackusa指出的错误。见 https://3v4l.org/hIVfb