Transpose 2D array structure [duplicate] - php

This question already has answers here:
Transposing multidimensional arrays in PHP
(12 answers)
Closed 6 months ago.
I don't think this can be done (with out my own function), however I'll ask any way.
I have a array in PHP like
array(
'item1' => array(
'Hello',
'Good',
),
'item2' => array(
'World',
'Bye',
),
)
The individual fields come from a web form
I want to rearrange it to the following
array(
array(
'item1' => 'Hello',
'item2' => 'World',
),
array(
'item1' => 'Good',
'item2' => 'Bye',
),
)
Make an array of objects from the field arrays
I could write a function to do this.
However I was wondering can one of the built-in array functions achieve this for me?

There is no built in function to do this - but here is a user-defined one that will:
function convert_array ($array) {
$result = array();
foreach ($array as $key => $inner) {
for ($i = 0; isset($inner[$i]); $i++) {
$result[$i][$key] = $inner[$i];
}
}
return $result;
}
See it working

Most certainly not the most efficient, but as close to "one function" as you'll get. ;)
array_map(function ($i) use ($array) { return array_combine(array_keys($array), $i); }, call_user_func_array('array_map', array_merge(array(function () { return func_get_args(); }), $array)));
See http://codepad.viper-7.com/xIn3Oq.

No. There is no built in function that would do this.

Related

Return last set of array from PHP recursive function [duplicate]

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I am trying to filter set of array through recursive function but can not return it when filtered is done.
function get_the_answer($number, $array=array()){
$returnArray = array();
$QS = array(1=>'C', 2=>'B', 3=>'C', 4=>'D');
$SL = array(
1 => array(
'cb1' => array('A','B', 'D'),
'cb2' => array('B','C', 'D'),
'cb3' => array('A','C', 'B'),
),
2 => array(
'cb1' => array('B','C','D'),
'cb2' => array('A','C','D'),
'cb3' => array('A','B','D'),
),
3 => array(
'cb1' => array('E','C','D'),
'cb2' => array('B','E','D'),
'cb3' => array('A','C','D'),
),
4 => array(
'cb1' => array('A','D','E'),
'cb2' => array('A','C','D'),
'cb3' => array('B','C','D'),
)
);
if($number<=4){
if(empty($array)){
$returnedValue = return_filtered_company($SL[$number], $QS[$number]);
} else {
$returnedValue = return_filtered_company($array, $QS[$number]);
}
//print_r($returnedValue); -> receiving values nicely, need the last set of array which is 'cb3'
$returnArray[] = $returnedValue;
$increment = $number+1;
if($increment<=4){
$result=array_intersect_key($SL[$increment], $returnedValue);
get_the_answer($increment, $result);
}
}
return $returnArray;
}
//function for company calculation
function return_filtered_company($companyArray, $answer){
$foundCB=array();
if(is_array($companyArray) && count($companyArray)){
foreach ($companyArray as $name => $arrayVal){
if (in_array($answer, $arrayVal)) {
$foundCB[$name]=$name;
}
}
}
return $foundCB;
}
I am calling answer function like this way:
$ans = get_the_answer(1);
echo '<pre>';
print_r($ans);
echo '</pre>';
Everything is working fine but it is returning value which happened in 1st recursion not the last one. Answer should be cb3
Someone please help to find out what is/are the best solution to return last occurrence of recursion.
Replacing line 42 get_the_answer($increment, $result); with return get_the_answer($increment, $result); solves it.
See the screenshot

PHP : merge multiples arrays with common keys [duplicate]

This question already has answers here:
Merge two indexed arrays of indexed arrays based on first column value
(2 answers)
Closed 5 months ago.
I have 5 differents arrays in my script :
$array1 = array(
array( "id"=>"1", "title"=>"Batman" ),
array( "id"=>"2", "title"=>"Spiderman" ),
array( "id"=>"3", "title"=>"Titanic" ),
array( "id"=>"4", "title"=>"Dracula" ),
);
$array2 = array(
array( "id"=>"1", "releasedate"=>"1926" ),
array( "id"=>"2", "releasedate"=>"1956" ),
array( "id"=>"3", "releasedate"=>"2001" ),
array( "id"=>"4", "releasedate"=>"1982" ),
);
etc ...
As you see, info about movie number 1 is splitted on all the arrays (in fact -> 5 arrays). Then I would like to merge all my arrays to get something like this :
$array_FINAL = array(
array( "id"=>"1", "title"=>"Batman", "releasedate"=>"1926" ),
array( "id"=>"2", "title"=>"Spiderman", "releasedate"=>"1956" ),
array( "id"=>"3", "title"=>"Titanic", "releasedate"=>"2001" ),
array( "id"=>"4", "title"=>"Dracula", "releasedate"=>"1982" ),
);
I tried array_merge, array_combine, no good results. I also checked other topics on stackoverflow but no one help me (i may miss the one i need!)
Any help ? :)
EDIT : Sorry, i did would give a little more details ... rows in the arrays could be in misc. order, then according to my code example : the movie "Batman" can be in 1st row in the first array, but in the 3rd row in the second array...
If the order of both arrays is the same, you can simply use
$array_final = array_replace_recursive($array1, $array2);
However, if you want to merge them by the "id", you need to loop through them. A solution with the complexity O(m*n):
$array_final = array();
// loop through all movies in array1
foreach($array1 as $movie){
foreach($array2 as $movie_release) {
if ($movie['id'] == $movie_release['id']) {
$movie['releasedate'] = $movie_release['releasedate'];
break;
}
}
$array_final[] = $movie;
}
And a little less complex O(m+n):
// create arrays with the ID as key
$titles = array_column($array1, 'title', 'id');
$releasedates = array_column($array2, 'releasedate', 'id');
$array_final = array();
foreach($titles as $id => $title) {
$array_final[] = array(
'id' => $id,
'title' => $title,
'releasedate' => $releasedates[$id]
);
}
One of the solutions is:
$array1 = array(
array( "id"=>"1", "title"=>"Batman" ),
array( "id"=>"2", "title"=>"Spiderman" ),
array( "id"=>"3", "title"=>"Titanic" ),
array( "id"=>"4", "title"=>"Dracula" ),
);
$array2 = array(
array( "id"=>"1", "releasedate"=>"1926" ),
array( "id"=>"2", "releasedate"=>"1956" ),
array( "id"=>"3", "releasedate"=>"2001" ),
array( "id"=>"4", "releasedate"=>"1982" ),
);
// here we create pairs `id => releasedate`
$new_array2 = [];
foreach ($array2 as $v) {
$new_array2[$v['id']] = $v['releasedate'];
}
foreach ($array1 as &$value) {
// here we try to find key `$value['id']` in `$new_array2`
// and get it's value
if (isset($new_array2[$value['id']])) {
$value['releasedate'] = $new_array2[$value['id']];
}
}
If you're 100% sure that orders of ids are the same in both arrays you can just:
$i = 0;
foreach ($array1 as &$value) {
$value['releasedate'] = $array2[$i]['releasedate'];
$i++;
}
See this code prototype (it is simple and don't need to explanations I believe):
$fArr = [];
for ( $i = 1; $i <= 4; $i++ ) {
$fArr[] = [
'id' => $i,
'title' => $array1[$i - 1]['title'],
'releasedate' => $array2[$i - 1]['releasedate'],
];
}
Sandbox code example
Assuming all of your five arrays contain the id key, you can do this with a nested foreach loop.
foreach (array_merge($array1, $array2, $array3, $array4, $array5) as $item) {
foreach ($item as $key => $value) {
$result[$item['id']][$key] = $value;
}
}
The outer foreach iterates all the rows in all the arrays. The inner one loops over each column and assigns its value to the corresponding key in the result array.

Flatten array while keeping into account the parent keys [duplicate]

This question already has answers here:
Turning multidimensional array into one-dimensional array [duplicate]
(11 answers)
Closed 4 years ago.
I need to flatten an array while making sure that there are no duplicate keys.
For instance let's say I have this:
$arr = array(
$foo = array(
'donuts' => array(
'name' => 'lionel ritchie',
'animal' => 'manatee',
)
)
);
I need a flattened array that looks like this:
$arr = array(
'donuts name' => 'lionel ritchie',
'donuts animal' => 'manatee',
);
It needs to work even if we have more than 1 parent keys.
I have the following code, but I am not sure I can work with this.
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array1)) as $k=>$v){
$array1c[$k] = $v;
}
It's very simple to do, just make it like this:
$arr = array(
$foo = array(
'donuts' => array(
'name' => 'lionel ritchie',
'animal' => 'manatee',
)
)
);
// Will loop 'donuts' and other items that you can insert in the $foo array.
foreach($foo as $findex => $child) {
// Remove item 'donuts' from array, it will get the numeric key of current element by using array_search and array_keys
array_splice($foo, array_search($findex, array_keys($foo)), 1);
foreach($child as $index => $value) {
// Adds an array element for every child
$foo[$findex.' '.$index] = $value;
}
}
Result of var_dump($foo); will be:
array(2) {
["donuts name"]=>
string(14) "lionel ritchie"
["donuts animal"]=>
string(7) "manatee"
}
Just try :)

Numerically sorting arrays output [duplicate]

This question already has answers here:
How do I Sort a Multidimensional Array in PHP [duplicate]
(10 answers)
Closed 8 years ago.
I'm trying to sort the output value that's returned by greatest to least.
Here's an example of the array:
array(
'ACTION' => 'getsupportdepartments',
'RESULT' => 'success',
'TOTALRESULTS' => 2,
'DEPARTMENTS' => array(
'DEPARTMENT' => array(
'ID' => 2,
'NAME' => 'Sales',
'AWAITINGREPLY' => 5,
'OPENTICKETS' => 5
),
'DEPARTMENT1' => array(
'ID' => 1,
'NAME' => 'Support',
'AWAITINGREPLY' => 15,
'OPENTICKETS' => 15
The code I'm using is:
if(!empty($_GET['sort'])) {
$tmpArray = array();
foreach($arr['WHMCSAPI']['DEPARTMENTS'] as $key => $value) {
$tmpArray[$value['AWAITINGREPLY']] = $value;
}
$arr['WHMCSAPI']['DEPARTMENTS'] = $tmpArray;
($_GET['sort'] == 'desc') ? krsort($arr['WHMCSAPI']['DEPARTMENTS']) : ksort($arr['WHMCSAPI']['DEPARTMENTS']);
}
($_GET['sort'] == 'desc') ? krsort($arr['WHMCSAPI']['DEPARTMENTS']) : ksort($arr['WHMCSAPI']['DEPARTMENTS']);
foreach($arr['WHMCSAPI']['DEPARTMENTS'] as $department) {
echo $department['NAME'].' - '.$department['AWAITINGREPLY'].'<br />';
}
echo $exc;
However the order of the output from AWAITINGREPLY is not sorting.
No need to reinvent the wheel, there's already a function called usort:
online demo
function sortDepts(array &$arr,$sort="desc")
{
if($sort=="desc")
usort($arr["DEPARTMENTS"],function($a,$b){
return $b["AWAITINGREPLY"]-$a["AWAITINGREPLY"];
});
else
usort($arr["DEPARTMENTS"],function($a,$b){
return $a["AWAITINGREPLY"]-$b["AWAITINGREPLY"];
});
return $arr;
}
Note that anonymous function works in PHP>=5.3. If you need to support 5<=PHP<5.3, you'll need to declare the function first.
Edit:
For 5 < PHP < 5.3:
online demo
function asc($a,$b)
{
return $a["AWAITINGREPLY"]-$b["AWAITINGREPLY"];
}
function desc($a,$b)
{
return $b["AWAITINGREPLY"]-$a["AWAITINGREPLY"];
}
function sortDepts(array &$arr,$sort="desc")
{
if($sort=="desc")
usort($arr["DEPARTMENTS"],"desc");
else
usort($arr["DEPARTMENTS"],"asc");
return $arr;
}
Edit #2:
In case you still need the key (DEPARTMENT,DEPARTMENT1,etc.), use uasort instead of usort (no other code change is required).

How to randomly loop through first layer of nested associative array in PHP?

I have a nested assocative array which might look something like this:
$myarray = array(
['tiger'] => array(
['people'], ['apes'], ['birds']
),
['eagle'] => array(
['rodents'] => array(['mice'], ['squirrel'])
),
['shark'] => ['seals']
);
How can I loop through the first layer (tiger, eagle, shark) in a random order and ensure that I cover them all in my loop? I was looking at the PHP function shuffle();, but I think that function messes up the whole array by shuffling all layers.
You can randomly sort an array like this, it will keep the keys and the values
<?php
$myarray = array(
'tiger' => array(
'people', 'apes', 'birds'
),
'eagle' => array(
'rodents' => array('mice', 'squirrel')
),
'shark' => 'seals'
);
$shuffleKeys = array_keys($myarray);
shuffle($shuffleKeys);
$newArray = array();
foreach($shuffleKeys as $key) {
$newArray[$key] = $myarray[$key];
}
print_r($newArray);
You can get the keys using array_keys(). Then you can shuffle the resulting key array using shuffle() and iterate through it.
Example:
$keys = array_keys($myarray);
shuffle($keys);
foreach ($keys as $key) {
var_dump($myarray[$key]);
}
According to my test, shuffle only randomizes 1 layer. try it yourself:
<?php
$test = array(
array(1,2,3,4,5),
array('a','b','c','d','e'),
array('one','two','three','four','five')
);
shuffle($test);
var_dump($test);
?>

Categories