Little complex to explain , so here is simple concrete exemple :
array 1 :
Array
(
[4] => bim
[5] => pow
[6] => foo
)
array 2 :
Array
(
[n] => Array
(
[0] => 1
)
[m] => Array
(
[0] => 1
[1] => 2
)
[l] => Array
(
[0] => 1
[1] => 4
[2] => 64
)
And i need to output an array 3 ,
array expected :
Array
(
[bim] => n-1
[pow] => Array
(
[0] => m-1
[1] => m-2
)
[foo] => Array
(
[0] => l-1
[1] => l-4
[2] => l-64
)
Final echoing OUTPUT expected:
bim n-1 , pow m-1 m-2 ,foo l-1 l-4 l-64 ,
I tried this but seems pity:
foreach($array2 as $k1 =>$v1){
foreach($array2[$k1] as $k => $v){
$k[] = $k1.'_'.$v);
}
foreach($array1 as $res =>$val){
$val = $array2;
}
Thanks for helps,
Jess
CHALLENGE ACCEPTED
<?php
$a = array(
4 => 'bim',
5 => 'pow',
6 => 'foo',
);
$b = array(
'n' => array(1),
'm' => array(1, 2),
'l' => array(1, 4, 64),
);
$len = count($a);
$result = array();
$aVals = array_values($a);
$bKeys = array_keys($b);
$bVals = array_values($b);
for ($i = 0; $i < $len; $i++) {
$combined = array();
$key = $aVals[$i];
$prefix = $bKeys[$i];
$items = $bVals[$i];
foreach ($items as $item) {
$combined[] = sprintf('%s-%d', $prefix, $item);
};
if (count($combined) === 1) {
$combined = $combined[0];
}
$result[$key] = $combined;
}
var_dump($result);
?>
Your code may be very easy. For example, assuming arrays:
$one = Array
(
4 => 'bim',
5 => 'pow',
6 => 'foo'
);
$two = Array
(
'n' => Array
(
0 => 1
),
'm' => Array
(
0 => 1,
1 => 2
),
'l' => Array
(
0 => 1,
1 => 4,
2 => 64
)
);
You may get your result with:
$result = [];
while((list($oneKey, $oneValue) = each($one)) &&
(list($twoKey, $twoValue) = each($two)))
{
$result[$oneValue] = array_map(function($item) use ($twoKey)
{
return $twoKey.'-'.$item;
}, $twoValue);
};
-check this demo Note, that code above will not make single-element array as single element. If that is needed, just add:
$result = array_map(function($item)
{
return count($item)>1?$item:array_shift($item);
}, $result);
Version of this solution for PHP4>=4.3, PHP5>=5.0 you can find here
Update: if you need only string, then use this (cross-version):
$result = array();
while((list($oneKey, $oneValue) = each($one)) &&
(list($twoKey, $twoValue) = each($two)))
{
$temp = array();
foreach($twoValue as $item)
{
$temp[] = $twoKey.'-'.$item;
}
$result[] = $oneValue.' '.join(' ', $temp);
};
$result = join(' ', $result);
As a solution to your problem please try executing following code snippet
<?php
$a=array(4=>'bim',5=>'pow',6=>'foo');
$b=array('n'=>array(1),'m'=>array(1,2),'l'=>array(1,4,64));
$keys=array_values($a);
$values=array();
foreach($b as $key=>$value)
{
if(is_array($value) && !empty($value))
{
foreach($value as $k=>$val)
{
if($key=='n')
{
$values[$key]=$key.'-'.$val;
}
else
{
$values[$key][]=$key.'-'.$val;
}
}
}
}
$result=array_combine($keys,$values);
echo '<pre>';
print_r($result);
?>
The logic behind should be clear by reading the code comments.
Here's a demo # PHPFiddle.
//omitted array declarations
$output = array();
//variables to shorten things in the loop
$val1 = array_values($array1);
$keys2 = array_keys($array2);
$vals2 = array_values($array2);
//iterating over each element of the first array
for($i = 0; $i < count($array1); $i++) {
//if the second array has multiple values at the same index
//as the first array things will be handled differently
if(count($vals2[$i]) > 1) {
$tempArr = array();
//iterating over each element of the second array
//at the specified index
foreach($vals2[$i] as $val) {
//we push each element into the temporary array
//(in the form of "keyOfArray2-value"
array_push($tempArr, $keys2[$i] . "-" . $val);
}
//finally assign it to our output array
$output[$val1[$i]] = $tempArr;
} else {
//when there is only one sub-element in array2
//we can assign the output directly, as you don't want an array in this case
$output[$val1[$i]] = $keys2[$i] . "-" . $vals2[$i][0];
}
}
var_dump($output);
Output:
Array (
["bim"]=> "n-1"
["pow"]=> Array (
[0]=> "m-1"
[1]=> "m-2"
)
["foo"]=> Array (
[0]=> "l-1"
[1]=> "l-4"
[2]=> "l-64"
)
)
Concerning your final output you may do something like
$final = "";
//$output can be obtained by any method of the other answers,
//not just with the method i posted above
foreach($output as $key=>$value) {
$final .= $key . " ";
if(count($value) > 1) {
$final .= implode($value, " ") .", ";
} else {
$final .= $value . ", ";
}
}
$final = rtrim($final, ", ");
This will echo bim n-1, pow m-1 m-2, foo l-1 l-4 l-64.
Related
I have one array like this :
$array='{b_price,9500,b_discount,10,mainPrice,95000,total,95000,title,obj1},{b_price,1500,b_discount,15,mainPrice,15000,total,22500,title,obj2}'
I want first split to two array like this :
$array[0]={b_price,9500,b_discount,10,mainPrice,95000,total,95000,title,obj1}
And
$array[1]={b_price,1500,b_discount,15,mainPrice,15000,total,22500,title,obj2}
I change every array with this code
foreach ($b as $k => $m) {
if ($k % 2 == 0) {
$even[]= $m;
}
else {
$odd[] = $m;
}
}
$ff=array_combine($even,$odd);
I want output change like this
Array( Array[0] => ([b_price] => 9500 [b_discount] => 10 [mainPrice] => 95000 [total] => 95000 [title] =>obj1)
Array[1] => ([b_price] => 1500 [b_discount] => 15 [mainPrice] => 15000 [total] => 22500 [title] => obj2))
Two approaches:
-- using explode and array_map functions:
$str = '{b_price,9500,b_discount,10,mainPrice,95000,total,95000,title,obj1},{b_price,1500,b_discount,15,mainPrice,15000,total,22500,title,obj2}';
$result = array_map(function($v){
$r = [];
$arr = explode(',', trim($v, '{}'));
foreach ($arr as $k => $v) {
if (!($k % 2)) $r[$v] = $arr[$k+1];
}
return $r;
}, explode('},{', $str));
print_r($result);
-- using additional preg_match_all and array_combine functions:
$str = '{b_price,9500,b_discount,10,mainPrice,95000,total,95000,title,obj1},{b_price,1500,b_discount,15,mainPrice,15000,total,22500,title,obj2}';
$result = array_map(function($v){
preg_match_all('/([^,]+),([^,]+),?/', trim($v, '{}'), $m);
return array_combine($m[1], $m[2]);
}, explode('},{', $str));
print_r($result);
The output:
Array
(
[0] => Array
(
[b_price] => 9500
[b_discount] => 10
[mainPrice] => 95000
[total] => 95000
[title] => obj1
)
[1] => Array
(
[b_price] => 1500
[b_discount] => 15
[mainPrice] => 15000
[total] => 22500
[title] => obj2
)
)
you should change your needle, in your array string,
i have changed it with semicolon,
$arrayString='{b_price,9500,b_discount,10,mainPrice,95000,total,95000,title,obj1};{b_price,1500,b_discount,15,mainPrice,15000,total,22500,title,obj2}';
echo $arrayString;
echo "<pre>"; print_r (explode(";",$arrayString));
$b=explode(";",$arrayString);
foreach ($b as $k => $m) {
if ($k % 2 == 0) {
$even[]= $m;
}
else {
$odd[] = $m;
}
}
$ff=array_combine($even,$odd);
So, I write this decision. Maybe it can be more clear, but it works.
$array='{b_price,9500,b_discount,10,mainPrice,95000,total,95000,title,obj1},{b_price,1500,b_discount,15,mainPrice,15000,total,22500,title,obj2}';
/*Making array from string*/
$tmp_array = explode("},{", $array);
/*Removing { symbols*/
$tmp_array[0] = substr($tmp_array[0],1);
$tmp_array[1] = substr($tmp_array[1],0,-1);
/*Making arrays from string [0] and [1]*/
$tmp_array[0] = explode(',',$tmp_array[0]);
$tmp_array[1] = explode(',',$tmp_array[1]);
$new_array = [];
/*Creating associative arrays*/
for($a = 0; $a < count($tmp_array); $a++) {
$new_as_array = [];
for($i = 0; $i <= count($tmp_array[0]); $i+=2) {
if($i + 1 <= count($tmp_array[0])) {
$new_as_array[$tmp_array[$a][$i]] = $tmp_array[$a][$i + 1];
}
}
$new_array[] = $new_as_array;
}
print_r($new_array);
I want to concat values of array with same key
Example:
[0] => Array
(
[0] => A
[1] => XYZ
)
[1] => Array
(
[0] => B
[1] => ABC
)
[2] => Array
(
[0] => A
[1] => LMN
)
[3] => Array
(
[0] => B
[1] => PQR
)
)
Expected output:
[0] => Array
(
[0] => A
[1] => XYZ,LMN
)
[1] => Array
(
[0] => B
[1] => ABC,PQR
)
)
A simple solution uses the PHP function array_reduce():
// The input array you posted in the question
$input = array(
array('A', 'XYZ'),
array('B', 'ABC'),
array('A', 'LMN'),
array('B', 'PQR'),
);
// Reduce the array to a new array that contains the data aggregated as you need
$output = array_reduce(
// Process each $item from $input using a callback function
$input,
// The callback function processes $item; the partial result is $carry
function (array $carry, array $item) {
// Extract the key into a variable
$key = $item[0];
// If the key was encountered before
// then a partial entry already exists in $carry
if (isset($carry[$key])) {
// Append the desired value to the existing entry
$carry[$key][1] .= ','.$item[1];
} else {
// Create a new entry in $carry (copy $item to key $key for quick retrieval)
$carry[$key] = $item;
}
// Return the updated $carry
return $carry;
},
// Start with an empty array (it is known as $carry in the callback function)
array()
);
// $output contains the array you need
Try this:
$final = array();
foreach ($array_items as $item)
{
$key = $item[0];
$found_index = -1;
for ($i=0; $i<count($final); $i++)
{
if ($key == $final[$i][0])
{
$found_index = $i;
break;
}
}
if ($found_index == -1)
{
$final_item = array();
$final_item[0] = $key;
$final_item[1] = $item[1];
$final[] = $final_item;
}
else
{
$final[$found_index][1] .= ",".$item[1];
}
}
We create a new array $final, and loop through your old array $array_items. For each item, we see if there is already an item in $final that has the same [0] index. If it doesn't exist, we create it and add the initial string to the [1] index. If it does exist, we just have to add the string onto the end of the [1] index.
Try it, substituting $array_items for whatever your array is called, let me know if it works.
Check my solution. It should work fine. I hope it will help you much.
$result = $passed_keys = $extended_arr = [];
foreach ($arr as $k => $value) {
for($i = $k + 1; $i < count($arr); $i++){
if ( $value[0] == $arr[$i][0] ){ // compare each array with rest subsequent arrays
$key_name = $value[0];
if (!array_key_exists($key_name, $result)){
$result[$key_name] = $value[1] .",". $arr[$i][1];
} else {
if (!in_array($i, $passed_keys[$key_name])) {
$result[$key_name] .= ",". $arr[$i][1];
}
}
$passed_keys[$key_name][] = $i; // memorizing keys that were passed
}
}
}
array_walk($result, function($v, $k) use(&$extended_arr){
$extended_arr[] = [$k, $v];
});
The result is in $extended_arr
My solution, creates a custom key which makes identifying the letter much easier. This removes the need to continuously iterate through each array, which can become a major resources hog.
<?php
$inital_array = array(
array('A','XYZ'),
array('B','ABC'),
array('A','LMN'),
array('B','PQR')
);
$concat_array = array();
foreach($inital_array as $a){
$key = $a[0];
if( !isset($concat_array[$key]) ){
$concat_array[$key] = array($key,'');
}
$concat_array[$key][1] .= (empty($concat_array[$key][1]) ? '' : ',').$a[1];
}
$concat_array = array_values($concat_array);
echo '<pre>',print_r($concat_array),'</pre>';
I'm trying to group airlines with relations into single chains.
Array
(
[0] => Array
(
[0] => Aeroflot
[1] => S7
[2] => Transaero
)
[1] => Array
(
[0] => Alitalia
[1] => Lufthansa
)
[2] => Array
(
[0] => Transaero
[1] => United
)
[3] => Array
(
[0] => United
[1] => Alitalia
)
[4] => Array
(
[0] => Volotea
[1] => Iberia
)
[5] => Array
(
[0] => Transaero
[1] => Aeroflot
)
)
From that array I need to find connections between elements and combine it to groups. Expected results:
Array
(
[0] => Array
(
[0] => Aeroflot
[1] => S7
[2] => Transaero
[3] => United
[4] => Alitalia
[5] => Lufthansa
)
[1] => Array
(
[0] => Volotea
[1] => Iberia
)
)
Can anyone help with that? I've tried a dozen of ways but still get no success.
The most closest way I've tried which works but not in all cases:
function array_searchRecursive($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && array_searchRecursive($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
foreach ($newarr as $key => $airlines)
{
foreach ($airlines as $lastkey => $airline)
{
$index = array_searchRecursive($airline,$newarr);
echo $airline.$index."\n";
if ($index !== false)
{
$newarr[$index] = array_merge($newarr[$index],$airlines);
$lastarr[] = $index;
}
}
}
But it doesn't match all values in array.
Recursive function will help you. You are welcome )
$arr = array(
array('Aeroflot','S7','Transaero'),
array('Alitalia','Lufthansa'),
array('Transaero','United'),
array('United','Alitalia'),
array('Volotea','Iberia'),
array('Transaero','Aeroflot')
);
function getConnections($arr,$curr_line_n=0,$num=0) {
for($i=0;$i<count($arr[$curr_line_n]);$i++) {
$cur_air_name = $arr[$curr_line_n][$i];
for($k=$curr_line_n+1; $k<count($arr); $k++) {
for($l=0;$l<count($arr[$k]);$l++) {
if ($arr[$k][$l]==$cur_air_name) {
$arr[$curr_line_n] = array_values(array_unique(array_merge($arr[$curr_line_n],$arr[$k])));
array_splice($arr,$k,1);
$num++;
$arr = getConnections($arr,$curr_line_n,$num);
}
}
}
}
$num++;
$curr_line_n++;
if ($curr_line_n!=count($arr)) {
$arr = getConnections($arr,$curr_line_n,$num);
}
return $arr;
}
print_r(getConnections($arr));
As per your example you are just grouping sub arrays by taking first sub array as reference. for example if you have any elements common in first sub array and in subsequent sub arrays then you combine them into one sub array.
<?php
$arr = array(
array('a', 'b', 'c', 'd'),
array('d', 't'),
array('t', 'f'),
array('k', 'o'),
array('p', 'z')
);
$arr_implode = array();
foreach ($arr as $key => $value) {
if (is_array($value)) {
$arr_implode[$key] = implode('', $value);
} else {
$arr_implode[$key] = $value;
}
}
$arr_key = array();
$result = array();
$count = count($arr_implode);
$tempj = 0;
for ($i = 0; $i <= $count; $i++) {
$flag = FALSE;
for ($j = ($i + 1); $j < $count; $j++) {
similar_text($arr_implode[$i], $arr_implode[$j], $percent);
if ($percent > 0) {
$result[] = array_merge($arr[$i],$arr[$j]);
break;
} else {
$result[] = $arr[$j];
break;
}
}
}
foreach($result as $key => $val){
$result[$key] = array_unique($val);
}
echo "<pre>";
print_r($result);
echo "</pre>";
?>
Try this code.
$arr = [
['Aeroflot', 'S7', 'Transaero'],
['Alitalia', 'Lufthansa'],
['Transaero', 'United'],
['United', 'Alitalia'],
['Volotea', 'Iberia'],
['Transaero', 'Aeroflot']
];
$hash = [];
$result = [];
foreach($arr as $set){
foreach($set as $el){
if(!$hash[$el]) $hash[$el] = [] ;
$hash[$el] = array_merge($hash[$el], $set);
}
}
function merge_connections(&$h, $key){
if(!$h[$key]) return [];
$data = [$key];
$rels = $h[$key];
unset($h[$key]);
foreach($rels as $rel){
if($rel==$key) continue;
$data = array_merge($data, merge_connections($h, $rel));
}
return $data;
}
foreach(array_keys($hash) as $company){
if(!$hash[$company]) continue;
array_push($result, merge_connections($hash, $company));
}
print_r($result);
How can the array be separated into groups of identical elements (concatenated chars).
For example, I have this array:
Array(
[0] => 1
[1] => 1
[2] => 1
[3] => 2
[4] => 2
[5] => 1
)
and want to group all identical numbers in only one element, bringing the together with concatenation to get something like this:
Array(
[0] => 111
[1] => 22
[2] => 1
)
To group all identical elements by concatenating them together (will not work for concatenating just the neighboring identical elements)
$arr = array (1,1,1,2,2,1);
$sum = array_count_values($arr);
array_walk($sum, function(&$count, $value) {
$count = str_repeat($value, $count);
});
print_r($sum);
Output
Array (
[1] => 1111
[2] => 22 )
Or for concatenating just the neighboring identical elements
$prev=null;
$key=0;
foreach ( $arr as $value ) {
if ($prev == $value){
$res[$key] .= $value;
} else {
$key++;
$res[$key] = $value;
$prev=$value;
}
}
print_r($res);
Output
Array (
[1] => 111
[2] => 22
[3] => 1 )
Here two functions
1 will return
Array
(
[1] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
)
[2] => Array
(
[0] => 2
[1] => 2
)
)
as output and second one will return
Array
(
[1] => 1111
[2] => 22
)
as output
$array = array(
1,1,1,2,2,1
);
print_r(groupArray($array));
print_r(groupSame($array));
function groupArray($array){
$temp = array();
foreach($array as $value){
if(!isset($temp[$value])){
$temp[$value] = array();
}
array_push($temp[$value],$value);
}
return $temp;
}
function groupSame($array){
$temp = array();
foreach($array as $value){
if(!isset($temp[$value])){
$temp[$value] = "";
}
$temp[$value] .= $value;
}
return $temp;
}
<?php
$i=0;
foreach($Arrays as $key=>$val) {
if (!isset($array[$i]))
$array[$i]=$val;
else if (!isset($mem) || $val==$mem)
$array[$i]=10*$array[$i]+$mem;
else
$i++;
$mem=$val;
}
?>
$array = array(1,1,1,2,2,1);
$start = "";
$new_array = array();
foreach($array as $v){
$v = (string)$v;
if($start==$v){
$count = count($new_array) - 1;
$val = $new_array[$count].$v;
$new_array[$count] = $val;
} else{
$new_array[] = $v;
}
$start = $v;
}
var_dump($new_array);
Tested and its working..
Output > array(3) { [0]=> string(3) "111" [1]=> string(2) "22" [2]=> string(1) "1" }
$newarray = array_unique($oldarray);
$count = array_count_values($oldarray);
foreach($newarray as &$val){
$val = str_repeat($val,$count[$val]);
}
http://codepad.org/FUf0n8sz
It should quite simple algorithm, but I just can't get around it.
I have some arrays in alphabetical order
[0] => Array
(
[0] => a
[1] => b
[2] => c
)
and for example
[0] => Array
(
[0] => a
[1] => b
[2] => c
[3] => d
)
and I need to sort them into rows. For example:
I should receive a table with 3 columns and as many rows as it may get and it should be in alphabetical order.
Here is an example:
First array should be converted into
[0] => Array
(
[0] => Array
(
[0] => a
[1] => b
[2] => c
)
)
But second one should be as
[1] => Array
(
[0] => Array
(
[0] => a
[1] => c
[2] => d
)
[1] => Array
(
[0] => b
)
)
I'm writing it in php, so if anyone can help I would be really appreciated.
UPD:
Code example:
function sortAsOrdered( array $categories )
{
foreach ( $categories as $groupId => $group )
{
$regroupMenuItems = array();
$limit = count( $group );
$rows = ceil( $limit / 3 );
for ( $i = 0; $i < $rows; ++$i )
{
$jumper = 0;
for ( $j = 0; $j < 3; $j++ )
{
if ( 0 == $jumper )
{
$jumper = $i;
}
if ( isset( $group[ $jumper ] ) )
{
$regroupMenuItems[ $i ][ $j ] = $group[ $jumper ];
}
$jumper = $jumper + $rows;
}
}
$categories[ $groupId ] = $regroupMenuItems;
}
return $categories;
}
Guys I solved this one. Here you could see my algorithm http://pastebin.com/xe2yjhYW.
But don't be sad your help will not go in vain. I probably will place bounty just for those who helped with this dificult algorithm for me.
Guys thanks one more time. Your thoughts inspired me to think differently.
array_chunk() wold have been the solution but as you want it to be specially sorted, that wouldn't help you much.
So here is my five cents:
function array_chunk_vertical($input, $size_max) {
$chunks = array();
$chunk_count = ceil(count($input) / $size_max);
$chunk_index = 0;
foreach ($input as $key => $value) {
$chunks[$chunk_index][$key] = $value;
if (++$chunk_index == $chunk_count) {
$chunk_index = 0;
}
}
return $chunks;
}
$array = array('a', 'b', 'c', 'd', 'e', 'f');
var_dump(array_chunk_vertical($array, 2));
Which will give you:
array
0 =>
array
0 => string 'a' (length=1)
3 => string 'd' (length=1)
1 =>
array
1 => string 'b' (length=1)
4 => string 'e' (length=1)
2 =>
array
2 => string 'c' (length=1)
5 => string 'f' (length=1)
The downside of this function is that you can only tell the max number of elements in a chunk, and then it equally divides the array to chunks. So for [4] and max_size 3 you will get [2,2] unlike the expected [3,1].
<?php
$five_el = array('a', 'b', 'c', 'd', 'e');
$two_el = array('a', 'b');
$three_el = array('a', 'b', 'c');
$six_el = array('a', 'b', 'c', 'd', 'e', 'f');
function multid($sorted_array) {
$mulidarray = array();
$row = 0;
$column = 0;
foreach ($sorted_array as $value) {
if ($column == 3) {
$row++;
}
$column++;
if (!isset($mulidarray[$row])) {
$mulidarray[$row] = array();
}
$multidarray[$row][] = $value;
}
return $multidarray;
}
var_dump(multid($five_el));
var_dump(multid($two_el));
var_dump(multid($three_el));
var_dump(multid($six_el));
array_chunk is a natural first approach to the problem, but it won't do exactly what you need to. If the solution is provided that way, you need to either restructure the resulting array or restructure the input before processing it, as below:
$input = range('a', 'k'); // arbitrary
$columns = 3; // configure this
$rows = ceil(count($input) / $columns);
// fugly, but this way it works without declaring a function
// and also in PHP < 5.3 (on 5.3 you'd use a lambda instead)
$order = create_function('$i',
'$row = (int)($i / '.$rows.');'.
'$col = $i % '.$rows.';'.
'return $col * ('.$columns.' + 1) + $row;');
// $order is designed to get the index of an item in the original array,
// and produce the index that item would have if the items appeared in
// column-major order instead of row-major as they appear now
$array = array_map($order, array_keys($input));
// replace the old keys with the new ones
$array = array_combine($array, $input);
// sort based on the new keys; this will effectively transpose the matrix,
// if it were already structured as a matrix instead of a single-dimensional array
ksort($array);
// done!
$array = array_chunk($array, $columns);
print_r($array);
See it in action.
Let's see if this is nearer the mark
function splitVerticalArrayIntoColumns($aInput, $iNumberOfColumns) {
//output array
$aOutput = array();
//the total length of the input array
$iInputLength = count($aInput);
//the number of rows will be ceil($iInputLength / $iNumberOfColumns)
$iNumRows = ceil($iInputLength / $iNumberOfColumns);
for($iInputIndex = 0; $iInputIndex < $iInputLength; $iInputIndex++) {
$iCurrentRow = $iInputIndex % $iNumRows;
$aOutput[$iCurrentRow][] = $aInput[$iInputIndex];
}
//return
return $aOutput;
}
Which - when run thus:
$aList = array("a", "e", "d", "b", "c");
echo 'array("a", "e", "d", "b", "c")' . "\n\n";
print_r(splitVerticalArrayIntoColumns($aList, 3));
Gives:
array("a", "e", "d", "b", "c")
Array
(
[0] => Array
(
[0] => a
[1] => d
[2] => c
)
[1] => Array
(
[0] => e
[1] => b
)
)
That's not sorting each row yet but is that the kind of thing you're after?
begin facepalm edit
... or of course, array_chunk($aList, 3) after you've sorted it O_o
http://uk3.php.net/manual/en/function.array-chunk.php
I'll leave everything below for reference or whatever - I'd completely forgotten about array_chunk()
end facepalm edit
I'd use a modulo in a loop where you're counting the array index (after sorting the array) - for instance if you're trying to split an array into 3 "columns" you could try something like:
if($iIndex % 3 == 0) {
//... create a new array
}
else {
//... add to an existing array
}
EDIT code example:
$aList = array("a", "e", "d", "b", "c");
sort($aList);
$iDesiredNumberOfColumns = 3;
$iListLength = count($aList);
$aListInColumns = array();
$iRowNumber = 0;
for($iIndex = 0; $iIndex < $iListLength; $iIndex++) {
$iColumnNumber = $iIndex % 3;
if($iIndex != 0 && $iColumnNumber == 0) {
$iRowNumber++;
}
$aListInColumns[$iRowNumber][$iColumnNumber] = $aList[$iIndex];
}
Just ran it on my local server (and corrected the typo), and it outputs as:
Array
(
[0] => Array
(
[0] => a
[1] => b
[2] => c
)
[1] => Array
(
[0] => d
[1] => e
)
)
There's probably a tidier way of doing it (that's a little procedural) but it should do the job.
How about:
$arrs = array(
array('a','b','c'),
array('a','b','c','d'),
array('a','b','c','d','e'),
array('a','b','c','d','e','f'),
array('a','b','c','d','e','f','g')
);
$nbcols = 3;
foreach ($arrs as $arr) {
$arr_size = count($arr);
$nblines = ceil($arr_size/$nbcols);
$res = array();
$l = 0;
foreach ($arr as $el) {
if ($l == $arr_size - 1 && count($res[0]) < $nbcols) $l=0;
$res[$l%$nblines][] = $el;
$l++;
}
print_r($res);
}
output:
Array
(
[0] => Array
(
[0] => a
[1] => b
[2] => c
)
)
Array
(
[0] => Array
(
[0] => a
[1] => c
[2] => d
)
[1] => Array
(
[0] => b
)
)
Array
(
[0] => Array
(
[0] => a
[1] => c
[2] => e
)
[1] => Array
(
[0] => b
[1] => d
)
)
Array
(
[0] => Array
(
[0] => a
[1] => c
[2] => e
)
[1] => Array
(
[0] => b
[1] => d
[2] => f
)
)
Array
(
[0] => Array
(
[0] => a
[1] => d
[2] => g
)
[1] => Array
(
[0] => b
[1] => e
)
[2] => Array
(
[0] => c
[1] => f
)
)
In order to do this, you need to do two operations:
First, split the array into 3 groups, as evenly as possible.
function array_grouped($arr, $group_count)
{
if (!count($arr)) return array();
$result = array();
for ($i = $group_count; $i > 0; --$i)
{
# break off the next ceil(remaining count / remaining columns) elements
# (avoiding FP math, cause that way lies madness)
$result[] = array_splice($arr, 0, ((count($arr)-1) / $i) + 1);
}
return $result;
}
Then, "transpose" the array, so that rows and columns switch places.
function array_transposed($arr)
{
$result = array();
foreach ($arr as $x => $subarr)
{
foreach ($subarr as $y => $val)
{
if (!isset($result[$y])) $result[$y] = array();
$result[$y][$x] = $val;
}
}
return $result;
}
array_transposed(array_grouped($arr, 3)) gives you entries in the order you want them.
YAYAYAY!! I've got it. You could turn this into a function if you'll be doing it regularly.
# Here we setup our array and the number of columns we want.
$myArray = range('a','d');
$numCols = 3;
# Here we break ourselves up into columns
for ($i = 0; $i < $numCols; $i++) {
$numRows = ceil(count($myArray) / ($numCols - $i));
$columns[$i] = array_slice($myArray,0,$numRows);
$myArray = array_slice($myArray,$numRows);
}
# Here we transpose our array to be in rows instead of columns.
for ($i = 0; $i < $numCols; $i++) {
for ($j = 0; $j < count($columns[$i]); $j++) {
$rows[$j][$i] = $columns[$i][$j];
}
}
# Our rows are now in $rows
var_dump($rows);
The output from this is:
array(2) {
[0]=>
array(3) {
[0]=>
string(1) "a"
[1]=>
string(1) "c"
[2]=>
string(1) "d"
}
[1]=>
array(1) {
[0]=>
string(1) "b"
}
}
If to say it shortly, then here is a method for that algorithm.
/**
* #param array $toTransform
* #param int $columnsMax
* #return array
*/
private function transformation( array $toTransform, $columnsMax = 3 )
{
// First divide array as you need
$listlen = count( $toTransform );
$partlen = floor( $listlen / $columnsMax );
$partrem = $listlen % $columnsMax;
$partition = array();
$mark = 0;
for ( $px = 0; $px < $columnsMax; $px++ )
{
$incr = ( $px < $partrem ) ? $partlen + 1 : $partlen;
$partition[ $px ] = array_slice( $toTransform, $mark, $incr );
$mark += $incr;
}
// Secondly fill empty slots for easy template use
$result = array();
for ( $i = 0; $i < count( $partition[0] ); $i++ )
{
$tmp = array();
foreach ( $partition as $column )
{
if ( isset( $column[ $i ] ) )
{
$tmp[] = $column[ $i ];
}
else
{
$tmp[] = '';
}
}
$result[] = $tmp;
}
return $result;
}
Also I included PHPUnit test for that. You can find it at, that link.