Better method of finding every possible combination of the partitioned sets - php

I need to find every possible combination of N sets of X length with no duplicates and in a particular order, e.g.
input: [["A"], ["B"], ["C"]]
output: [["A","B","C"],["A","B"],["A","C"],["B","C"],["A"],["B"],["C"]]
Rules:
The number or size of partitions is not fixed.
Only one member from each partition in each combination.
Combinations with more members are higher precedence.
Members earlier on in the input are higher precedence than members later on.
Another example with larger sets:
input: [["A","B"],["C","D","E"],["F"]]
output: [["A","C","F"],["A","D","F"],["A","E","F"],["B","C","F"],["B","D","F"],["B","E","F"],["A","C"],["A","D"],["A","E"],["B","C"],["B","D"],["B","E"],["A","F"],["B","F"],["C","F"],["D","F"],["E","F"],["A"],["B"],["C"],["D"],["E"],["F"]]
I've managed to get the output I want by combining the output of a power set function with a cartesian product function, but the resulting code isn't very concise or pretty. I was wondering if this could be better done with recursion?
Here's what I have already:
$test = json_decode('[["A"]]');
$test1 = json_decode('[["A"], ["B"], ["C"]]');
$test2 = json_decode('[["A", "B"], ["C", "D", "E"], ["F"]]');
/**
* Returns a power set of the input array.
*/
function power_set($in, $minLength = 1) {
$count = count($in);
$members = pow(2,$count);
$return = array();
for ($i = 0; $i < $members; $i++) {
$b = sprintf("%0".$count."b",$i);
$out = array();
for ($j = 0; $j < $count; $j++) {
if ($b[$j] == '1') {
$out[] = $in[$j];
}
}
if (count($out) >= $minLength) {
$return[] = $out;
}
}
return $return;
}
/**
* Returns the cartesian product of the input arrays.
*/
function array_cartesian() {
$_ = func_get_args();
if(count($_) == 0) {
return array(array());
}
$a = array_shift($_);
$c = call_user_func_array(__FUNCTION__, $_);
$r = array();
foreach($a as $v) {
foreach($c as $p) {
$r[] = array_merge(array($v), $p);
}
}
return $r;
}
/**
* Used with usort() to sort arrays by length, desc.
* If two arrays are the same length, then a sum of
* their keys is taken, with lower values coming first.
*/
function arraySizeDesc($a, $b) {
if(count($a) === count($b)) {
if(array_sum($a) === array_sum($b)) {
return 0;
}
return (array_sum($a) > array_sum($b)) ? 1 : -1;
}
return (count($a) < count($b)) ? 1 : -1;
}
/**
* Calculates a powerset of the input array and then uses
* this to generate cartesian products of each combination
* until all possible combinations are aquired.
*/
function combinations($in) {
$out = array();
$powerSet = power_set(array_keys($in));
usort($powerSet, 'arraySizeDesc');
foreach($powerSet as $combination) {
if(count($combination) < 2) {
foreach($in[$combination[0]] as $value) {
$out[] = array($value);
}
} else {
$sets = array();
foreach($combination as $setId) {
$sets[] = $in[$setId];
}
$out = array_merge($out, call_user_func_array('array_cartesian', $sets));
}
}
return $out;
}
echo "input: ".json_encode($test2);
echo "<br />output: ".json_encode(combinations($test2));
I realise the size of the output could grow very rapidly, but the input should only usually contain 1-5 sets of 1-50 members, so it doesn't need to deal with massive sets.

Essentially, your approach has been to generate the power-set of the input and then post-process that to arrive at your desired output.
One can approach it differently by attempting to solve it directly. One solution that came to me is the following.
Given an input A = [ A1, ...], assume the problem is already solved for A \ A1. Call this solution S'. How can we transform S' to the solution S for the whole of A? This is essentially by making two copy of S'. We distribute elements of A1 into the first copy. Let's call the new sequence S''. Thus the solution to A becomes simply a concatenation of S'' and S'.
Algorithmically,
Input: A = [ A1, A2, ..., An]
combine(A, i, n):
if n < i
return []
if n == i
return singletons(Ai)
S' = combine(A, i + 1, n)
S'' = [a, S'], for each a in Ai
return [S'', S']
The function singletons returns a family of one-element subsets of the input set. So, if it take the input [1, 2, 3], it'll return [[1], [2], [3]].
The approach should be clear if you ignore some loose usage of concatenation of sequences here and there ...
Good luck!

Try
$test = array ();
$test [0] = json_decode ( '[["A"]]', true );
$test [1] = json_decode ( '[["A"], ["B"], ["C"]]', true );
$test [2] = json_decode ( '[["A", "B"], ["C", "D", "E"], ["F"]]', true );
echo "<pre>" ;
$set = array ();
getSet ( $test, $set );
$set = array_values(array_unique($set));
$return = powerSet($set,1,3);
print_r ($return);
Output
Array
(
[0] => Array
(
[0] => F
)
[1] => Array
(
[0] => E
)
[2] => Array
(
[0] => E
[1] => F
)
[3] => Array
(
[0] => D
)
[4] => Array
(
[0] => D
[1] => F
)
[5] => Array
(
[0] => D
[1] => E
)
[6] => Array
(
[0] => D
[1] => E
[2] => F
)
[7] => Array
(
[0] => C
)
[8] => Array
(
[0] => C
[1] => F
)
[9] => Array
(
[0] => C
[1] => E
)
[10] => Array
(
[0] => C
[1] => E
[2] => F
)
[11] => Array
(
[0] => C
[1] => D
)
[12] => Array
(
[0] => C
[1] => D
[2] => F
)
[13] => Array
(
[0] => C
[1] => D
[2] => E
)
[14] => Array
(
[0] => B
)
[15] => Array
(
[0] => B
[1] => F
)
[16] => Array
(
[0] => B
[1] => E
)
[17] => Array
(
[0] => B
[1] => E
[2] => F
)
[18] => Array
(
[0] => B
[1] => D
)
[19] => Array
(
[0] => B
[1] => D
[2] => F
)
[20] => Array
(
[0] => B
[1] => D
[2] => E
)
[21] => Array
(
[0] => B
[1] => C
)
[22] => Array
(
[0] => B
[1] => C
[2] => F
)
[23] => Array
(
[0] => B
[1] => C
[2] => E
)
[24] => Array
(
[0] => B
[1] => C
[2] => D
)
[25] => Array
(
[0] => A
)
[26] => Array
(
[0] => A
[1] => F
)
[27] => Array
(
[0] => A
[1] => E
)
[28] => Array
(
[0] => A
[1] => E
[2] => F
)
[29] => Array
(
[0] => A
[1] => D
)
[30] => Array
(
[0] => A
[1] => D
[2] => F
)
[31] => Array
(
[0] => A
[1] => D
[2] => E
)
[32] => Array
(
[0] => A
[1] => C
)
[33] => Array
(
[0] => A
[1] => C
[2] => F
)
[34] => Array
(
[0] => A
[1] => C
[2] => E
)
[35] => Array
(
[0] => A
[1] => C
[2] => D
)
[36] => Array
(
[0] => A
[1] => B
)
[37] => Array
(
[0] => A
[1] => B
[2] => F
)
[38] => Array
(
[0] => A
[1] => B
[2] => E
)
[39] => Array
(
[0] => A
[1] => B
[2] => D
)
[40] => Array
(
[0] => A
[1] => B
[2] => C
)
)
Functions used
function powerSet($in, $minLength = 1, $max = 10) {
$count = count ( $in );
$members = pow ( 2, $count );
$return = array ();
for($i = 0; $i < $members; $i ++) {
$b = sprintf ( "%0" . $count . "b", $i );
$out = array ();
for($j = 0; $j < $count; $j ++) {
if ($b {$j} == '1')
$out [] = $in [$j];
}
if (count ( $out ) >= $minLength && count ( $out ) <= $max) {
$return [] = $out;
}
}
return $return;
}
function getSet($array, &$vals) {
foreach ( $array as $key => $value ) {
if (is_array ( $value )) {
getSet ( $value, $vals );
} else {
$vals [] = $value;
}
}
return $vals;
}

Related

Count consecutive repeated elements in array in the same sequence as they are

I need to count consecutive repeated elements in the array, but if they are non consecutive I want to count them also, to have them in the same sequence as they are.
For example I have flowing array:
$array = Array('a', 'b', 'a', 'a', 'a', 'c', 'c', 'b', 'b', 'a', 'a', 'a', 'a');
if I use array_count_values function
example:
print_r(array_count_values($array));
Output will be:
Array ( [a] => 8 [b] => 3 [c] => 2 )
But I need to get output like this:
element counted value
a 1
b 1
a 3
c 2
b 2
a 4
You can iterate over the array, counting values while they are the same, and pushing a value to the result array when they are different:
$result = [];
$count = 0;
$current = $array[0];
for ($i = 0; $i < count($array); $i++) {
if ($array[$i] == $current) {
$count++;
}
else {
$result[] = array($current, $count);
$count = 1;
}
$current = $array[$i];
}
$result[] = array($current, $count);
print_r($result);
Output:
Array
(
[0] => Array
(
[0] => a
[1] => 1
)
[1] => Array
(
[0] => b
[1] => 1
)
[2] => Array
(
[0] => a
[1] => 3
)
[3] => Array
(
[0] => c
[1] => 2
)
[4] => Array
(
[0] => b
[1] => 2
)
[5] => Array
(
[0] => a
[1] => 4
)
)
Demo on 3v4l.org
Starting with an array with the first item from the source (and a count of 1), this then starts from the second item and checks if it matches the one in the current output. Adding 1 if it matches or adding a new entry if it doesn't...
$array = Array ('a','b','a','a','a','c','c','b','b','a','a','a','a');
$output = [ ["element" => $array[0], "count" => 1 ] ];
$outputPoint = 0;
for ( $i = 1, $count = count($array); $i < $count; $i++ ) {
if ( $array[$i] == $output[$outputPoint]["element"] ) {
$output[$outputPoint]["count"]++;
}
else {
$output[++$outputPoint] = ["element" => $array[$i], "count" => 1 ];
}
}
print_r($output);
Which outputs...
Array
(
[0] => Array
(
[element] => a
[count] => 1
)
[1] => Array
(
[element] => b
[count] => 1
)
[2] => Array
(
[element] => a
[count] => 3
)
[3] => Array
(
[element] => c
[count] => 2
)
[4] => Array
(
[element] => b
[count] => 2
)
[5] => Array
(
[element] => a
[count] => 4
)
)
This loops through the array and increments the number of elements in $count.
$array = ['a','b','a','a','a','c','c','b','b','a','a','a','a'];
$count = [];
$crt = -1;
foreach($array ?? [] as $element) {
if($crt == -1 || $count[$crt]["element"] != $element) {
$count[++$crt] = ["element" => $element, "counted_value" => 1];
} else {
$count[$crt]["counted_value"]++;
}
}
The array looks like:
Array
(
[0] => Array
(
[element] => a
[counted_value] => 1
)
[1] => Array
(
[element] => b
[counted_value] => 1
)
[2] => Array
(
[element] => a
[counted_value] => 3
)
[3] => Array
(
[element] => c
[counted_value] => 2
)
[4] => Array
(
[element] => b
[counted_value] => 2
)
[5] => Array
(
[element] => a
[counted_value] => 4
)
)
Compare 2 elements by iterating the array, if both the elements are the same, increase the count else keep the count as 1
$index = 0;
$finalArr[$index] = array('ele'=>$array[0],'cnt'=>1);
for($i=1; $i<count($array); $i++)
{
if($array[$i]===$array[$i-1])
{
++$finalArr[$index]['cnt'];
}
else
{
$finalArr[++$index] = array('ele'=>$array[$i],'cnt'=>1);
}
}
print_r($finalArr);

php array unset not working as expected

I have an array of records I want to create a separate array of skills and want to remove duplicate values, unset not providing desired result somehow, I am not able to find out what's wrong. For example I have record (a) in first skills array at index 0 and I have same record in last skills array at index 1 , I just want to remove any duplicate records but unset removing other records also.
$x = 0;
$y = 0;
$z = 0;
$data = array();
$all_data = array ( 0 => array ( "fname" => "Ann", "skills" => array ( 0 => "a", 1 => "b" )),
1 => array ( "fname" => "Bxx", "skills" => array ( 0 => "c", 1 => "d" )),
2 => array ( "fname" => "Sdd", "skills" => array ( 0 => "e", 1 => "a" ))
);
while( $x < count($all_data)){
while($y < count($all_data[$x]['skills'])){
$data[$x] = $all_data[$x]['skills'];
if (in_array($data[$x][$y], $data[$x])){
unset($data[$x][$y]);
}
$y++;
}
$y = 0;
$x++;
}
The result I am getting is this
Array
(
[0] => Array
(
[0] => a
)
[1] => Array
(
[0] => c
)
[2] => Array
(
[0] => e
[1] => a
)
)
I am expecting
Array
(
[0] => Array
(
[0] => a
[1] => b
)
[1] => Array
(
[0] => c
[1] => d
)
[2] => Array
(
[0] => e
)
)
You could try something like this :
$keys=[];
foreach ($all_data as $index1 => $item) {
if (!isset($item['skills'])) continue;
foreach ($item['skills'] as $index2 => $value) {
if (!in_array($value, $keys)) {
$data[$index1][] = $value ;
$keys[] = $value ;
}
}
}
unset($keys);
print_r($data);
Outputs :
Array
(
[0] => Array
(
[0] => a
[1] => b
)
[1] => Array
(
[0] => c
[1] => d
)
[2] => Array
(
[0] => e
)
)

Find all possible permutations without repeating the value

Let's say I have this set of arrays as input:
[
0 => [1,2,4,5],
1 => [2,3,4],
2 => [1,3],
]
I would like to find all permutations possible selecting one value from each array. That value would be unique in the final result, so it won't repeat. For example, I can't have 1 twice in the result.
The count of arrays on input is the same as count of arrays on output.
Examples of combinations wanted (key=>value):
[0 => 1,1 => 2,2 => 3]
[0 => 2,1 => 3,2 => 1]
[0 => 5,1 => 2,2 => 1]
[0 => 1,1 => 3,2 => null]
Wrong results
[0 => 1,1 => 2,2 => 1]
or
[0 => 2,1 => 2,2 => 3]
I would like to get set of all possible permutations using PHP. How can I do that?
I have attached real data set http://pastebin.com/U6Hyawm4 However, I have no idea how many permutations there may be.
Here's a non-recursive version that's also optimized
/**
* Generates all the possible unique N-tuples from an array of N arrays of integers
*
* #param array $input
* #return array
*/
function generateCombinations(array &$input) {
// since the example results included [1, 3, null] I have assumed that
// null is a possible value of each set.
$sets = [];
foreach($input as $set) {
if(!in_array(null, $set)) {
$set[] = null;
}
$sets[] = $set;
}
// by working on the iterators of each array this loop
// linearizes the entire set of possible combinations
// and iterates it (skipping as many as it can).
$output = [];
$setCount = count($sets);
while(current($sets[0]) !== false) {
$testCombo = [];
for($setIdx = 0; $setIdx < $setCount; $setIdx++) {
if(!in_array(current($sets[$setIdx]), $testCombo)) {
$testCombo[] = current($sets[$setIdx]);
}
else {
// when a combination is thrown out as duplicate
// iterate to skip any other combo's that would also
// contain that duplicate
iterateSets($sets, $setIdx);
break;
}
}
// if there were no duplicates add it to the output and iterate
if(count($testCombo) == $setCount) {
$output[] = $testCombo;
iterateSets($sets, $setCount - 1);
}
}
return $output;
}
/**
* Iterates to the next potentially valid combination. I think of
* this like doing long-hand addition. Add 1 and carry is akin to
* next and reset.
*
* #param array $sets
* #param $index
*/
function iterateSets(array &$sets, $index) {
// reset iterators of all sets past the current one to skip
// combos that cannot be valid
for($i = $index + 1, $ic = count($sets); $i < $ic; $i++) {
reset($sets[$i]);
}
// always move one on current set
next($sets[$index]);
while($index > 0 && current($sets[$index]) === false) {
// wrap if current set is at the end
reset($sets[$index]);
$index--;
// move one for the preceding set
next($sets[$index]);
// then repeat
}
}
The resulting array is:
[
[1,2,3]
[1,2,null]
[1,3,null]
[1,4,3]
[1,4,null]
[1,null,3]
[2,3,1]
[2,3,null]
[2,4,1]
[2,4,3]
[2,4,null]
[2,null,1]
[2,null,3]
[4,2,1]
[4,2,3]
[4,2,null]
[4,3,1]
[4,3,null]
[4,null,1]
[4,null,3]
[5,2,1]
[5,2,3]
[5,2,null]
[5,3,1]
[5,3,null]
[5,4,1]
[5,4,3]
[5,4,null]
[5,null,1]
[5,null,3]
[null,2,1]
[null,2,3]
[null,3,1]
[null,4,1]
[null,4,3]
]
Here's an inefficient version:
$input = array(
[1,2,4,5],
[2,3,4],
[1,3]
);
function appendUnique($subs, $i) {
global $input;
if ($i == count($input)) {
return $subs;
}
$output = array();
foreach ($subs as $sub) {
foreach ($input[$i] as $v) {
$new_sub = array_values($sub);
if (in_array($v, $sub)) {
$new_sub[] = null;
} else {
$new_sub[] = $v;
}
$output[] = $new_sub;
}
}
return appendUnique($output, $i+1);
}
$output = appendUnique([[]], 0);
$output_json = array();
foreach ($output as $row) {
$output_json[] = json_encode($row);
}
$output_json = array_unique($output_json);
$deduped = array();
foreach ($output_json as $json) {
$deduped[] = json_decode($json);
}
print_r($deduped);
outputs:
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] =>
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[2] => Array
(
[0] => 1
[1] => 3
[2] =>
)
[3] => Array
(
[0] => 1
[1] => 4
[2] =>
)
[4] => Array
(
[0] => 1
[1] => 4
[2] => 3
)
[5] => Array
(
[0] => 2
[1] =>
[2] => 1
)
[6] => Array
(
[0] => 2
[1] =>
[2] => 3
)
[7] => Array
(
[0] => 2
[1] => 3
[2] => 1
)
[8] => Array
(
[0] => 2
[1] => 3
[2] =>
)
[9] => Array
(
[0] => 2
[1] => 4
[2] => 1
)
[10] => Array
(
[0] => 2
[1] => 4
[2] => 3
)
[11] => Array
(
[0] => 4
[1] => 2
[2] => 1
)
[12] => Array
(
[0] => 4
[1] => 2
[2] => 3
)
[13] => Array
(
[0] => 4
[1] => 3
[2] => 1
)
[14] => Array
(
[0] => 4
[1] => 3
[2] =>
)
[15] => Array
(
[0] => 4
[1] =>
[2] => 1
)
[16] => Array
(
[0] => 4
[1] =>
[2] => 3
)
[17] => Array
(
[0] => 5
[1] => 2
[2] => 1
)
[18] => Array
(
[0] => 5
[1] => 2
[2] => 3
)
[19] => Array
(
[0] => 5
[1] => 3
[2] => 1
)
[20] => Array
(
[0] => 5
[1] => 3
[2] =>
)
[21] => Array
(
[0] => 5
[1] => 4
[2] => 1
)
[22] => Array
(
[0] => 5
[1] => 4
[2] => 3
)
)

merge two array with different dimension

I have array A and B with the structure:
A:
Array
(
[0] => 2013-08-01
[1] => 2013-08-02
[2] => 2013-08-03
[3] => 2013-08-04
)
and B:
Array
(
[0] => Array
(
[0] => 2013-08-01
[1] => 2
[2] => 0
[3] => 0
)
[1] => Array
(
[0] => 2013-08-02
[1] => 0
[2] => 4
[3] => 0
)
[2] => Array
(
[0] => 2013-08-04
[1] => 0
[2] => 1
[3] => 0
)
)
The question is I want to combine twi ARRAY (A & B) to be like this:
Array
(
[0] => Array
(
[0] => 2013-08-01
[1] => 2
[2] => 0
[3] => 0
)
[1] => Array
(
[0] => 2013-08-02
[1] => 0
[2] => 4
[3] => 0
)
[2] => Array
(
[0] => 2013-08-03
[1] => 0
[2] => 0
[3] => 0
)
[3] => Array
(
[0] => 2013-08-04
[1] => 0
[2] => 1
[3] => 0
)
)
How to merge the both of array?
function combine($a, $b) {
foreach($a as $item_a) {
foreach($b as $item_b) {
if(in_array($item_a, $item_b)) {
continue 2;
}
}
$b[] = array(
$item_a, 0, 0, 0
);
}
usort($b, function($a, $b){return $a[0] > $b[0];});
return $b;
}
<?
$a = Array
(
"2013-08-01",
"2013-08-02",
"2013-08-03",
"2013-08-04"
);
$b = Array
(
Array (
"2013-08-01",
2,
0,
0
),
Array (
"2013-08-02",
0,
4,
0
),
Array (
"2013-08-04",
0,
1,
0
)
);
foreach ($a as $a_item) {
$found = FALSE;
foreach ($b as $b_item) {
if($b_item[0]==$a_item) {
$found = TRUE;
}
}
if(!$found) {
$b[] = Array (
$a_item,
0,
0,
0
);
}
}
print_r ($b);
?>
This should work if you don't have a huge amount of data in the arrays. If you have a large amount of data you should probably do some redesign to make it faster.
Assuming that the core dates are in array B, my approach would be to loop through array A and add to array B if a date is found that is not already in array B.
foreach ($arrA as $datecheck) {
$blnAdd = 1;
foreach ($arrB as $compare) {
if ($compare[0] == $datecheck) {
// If found, don't add!
$blnAdd = 0;
}
}
if ($blnAdd == 1) {
$arrB[] = array($datecheck, 0, 0, 0);
}
}
// When done, sort array B
// Create helper array for multisort
$arrHelper = array();
foreach ($arrB as $data) {
$arrHelper = $data[0];
}
// Then, sort array B using values from helper array
array_multisort($arrHelper, $arrB);
Then, $arrB should contain the values you need.

PHP merge single array elements into unique array

I'm not sure how to work the title of this question, so sorry if it's a little confusing.
I have an array;
Array
(
[username] => Array
(
[0] => 'a'
[1] => 'b'
[2] => 'c'
[3] => 'd'
[4] => 'e'
[5] => 'f'
)
[email] => Array
(
[0] =>
[1] =>
[2] =>
[3] =>
[4] =>
[5] =>
)
[level] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
[4] => 1
[5] => 1
)
[role] => Array
(
[0] => 2
[1] => 1
[2] => 1
[3] => 1
[4] => 2
[5] => 1
)
[password] => Array
(
[0] =>
[1] =>
[2] =>
[3] =>
[4] =>
[5] =>
)
[id] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)
)
But I want it in this format:
Array
(
[0] => Array
(
[username] => 'a'
[id] => 'a'
[email] => 'a'
)
[1] => Array
(
[username] => 'a'
[id] => 'a'
[email] => 'a'
)
[2] => Array
(
[username] => 'a'
[id] => 'a'
[email] => 'a'
)
[3] => Array
(
[username] => 'a'
[id] => 'a'
[email] => 'a'
)
[4] => Array
(
[username] => 'a'
[id] => 'a'
[email] => 'a'
)
[5] => Array
(
[username] => 'a'
[id] => 'a'
[email] => 'a'
)
I can't seem to figure it out, arrays end too soon, or there ends up being too many indexes etc. Ideas?
I would loop through the array and reconstruct it like so:
$index_count = count($array['username']); // in your case, this is 6
$new_array = array();
for ($i = 0; $i < $index_count; $i++) {
$new_array[] = array(
'username' => $array['username'][$i],
'email' => $array['email'][$i],
'id' => $array['id'][$i]
);
}
UPDATE If you want this to take into consideration any and all possible keys, try this:
$keys = array_keys($array);
if (count($keys)) {
$index_count = count($array[$keys[0]]);
$myArray = array();
for ($i = 0; $i < $index_count; $i++) {
$temp = array();
foreach($keys as $key) {
$temp[$key] = $array[$key][$i];
}
$myArray[] = $temp;
}
}
A different take, but here's what I would do - step by step:
First, let's get the keys - we'll be needing them a lot:
$result = array();//<-- this is the result array
$keys = array_keys($array);
Then, I'd get an empty, template array (somewhat like a model object)
$base = array_fill_keys($keys,array());
//array('username'=>array,'id'=>array(),...
Then, use that to build your result array:
$result = array_fill(0,count($array['username']),$base);
//In one-liner format, it looks like this:
$result = array_fill(0,count($array['username']),array_fill_keys(array_keys($array),array()));
//Works, but is messy as f***
Then just fill the lot, this is where that $keys variable pays off:
$length = count($result);
while ($key = array_shift($keys))
{
for ($i=0;$i<$length;$i++)
{
$result[$i][$key] = $array[$key][$i];
}
}
Note that I prefer using a while loop, as it is cleaner and (marginally) faster. Cleaner because that $keys array is being emptied as you go along. If you're working with substantial amounts of data it can sometimes make a difference. If the dataset is REALLY large, and the code has been thoroughly tested, you might even want to consider shifting from the source array (as it contains all data, it's a lot bigger than a an array containing just the keys):
while ($vals = array_shift($array))
{
$key = array_shift($keys);//<-- keep track of what array has been shifted
for ($i=0;$i<$length;$i++)
{
$result[$i][$key] = $vals[$i];
}
}
This neatly cleans up the source array, and the keys. I've tested this last approach on my server, writecodeonline and codepad, all with exactly the same results:
$foo = array('bar'=>array_fill(0,2,'ás'),'quar'=>range('a','z'));
$keys = array_keys($foo);
while($vals = array_shift($foo))
{
$key = array_shift($keys);
echo $key.' contains: => '.implode(', ',$vals).'<br/>';
}
bar contains: => ás, ás
quar contains: => a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z

Categories