How to Re-structure multi-dimensional array in PHP? - php

I have an array that looks like this:
array(3) {
[0]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(5) "3238"
}
[1]=>
array(2) {
[0]=>
string(10) "2012-11-13"
[1]=>
string(5) "3231"
}
[2]=>
array(2) {
[0]=>
string(10) "2012-11-13"
[1]=>
string(5) "3231"
}
I would like to write a foreach loop that would turn this array into:
array(2) {
[0]=>
array(1) {
"2012-11-14" => "3238"
}
[1]=>
array(1) {
"2012-11-13" => "3231"
}
So, basically, I would like to use the array element formatted as Y-M-D date as key to the second element in the array.

Given the following array...
$array = array(
0 => array(0 => "2012-11-14", 1 => "3238"),
1 => array(0 => "2012-11-13", 1 => "3231"),
2 => array(0 => "2012-11-13", 1 => "3231"),
);
putting it into a new array like this:
$new_array = array();
foreach ($array as $key => $item)
{
$new_array[$key][$item[0]] = $item[1];
}
print_r($new_array);
produces this output:
Array
(
[0] => Array
(
[2012-11-14] => 3238
)
[1] => Array
(
[2012-11-13] => 3231
)
[2] => Array
(
[2012-11-13] => 3231
)
)
My answer doesn't get rid of the duplicates, but the added dimension as specified in the original question means that duplicate dates as keys aren't an issue.

<?php
$data = array(
array("2012-11-14", "3238"),
array("2012-11-13", "3231"),
array("2012-11-13", "3231") // warning! when there are two record with same date, the second's count will be display
);
$result = array();
foreach ($data as $value) {
$result[$value[0]] = $value[1];
}
echo '<pre>';
print_r($result);

<?php
$newArray = array();
for($i=0;$i<count($arrayVariable);$i++)
{
$newArray[$arrayVariable[$i][0]] = $arrayVariable[$i][1];
}
echo '<pre>';print_r($newArray);echo '</pre>';
?>
Didn't test it but something like this should work in concept. Of course change arrayVariable to your variable.. but that aside.

You can use this code to get what you want:
$dates = array(
array("2012-11-01", "3238"),
array("2012-11-03", "4321")
);
print_r($dates);
$result = array();
foreach($dates as $value) {
$result[][$value[0]] = $value[1];
}
print_r($result);
The output will look like the requested form:
Array
(
[0] => Array
(
[2012-11-01] => 3238
)
[1] => Array
(
[2012-11-03] => 4321
)
)
Codepad demo: http://codepad.org/XAmUEdYh
However, I would personally prefer Aykut's solution. You would of course have a problem when you've got two records with the same date, but the overall array layout is a bit nicer ;).

Here is what I came up with:
<?php
$original = array(
array(
"2012-11-14",
"3238"
),
array(
"2012-11-13",
"3231"
),
array(
"2012-11-13",
"3231"
)
);
$newArray = array();
foreach($original as $subArray){
$newArray[] = array($subArray[0] => $subArray[1]);
}
var_dump($newArray);

Related

How to get hyrarchy from key elements and create new elements based on that - PHP

I have a very big array, I will try to explain the issue in small examples:
Input:
Array (
[alert:accountDisabled:heading] => XYZ
[alert:accountDisabled:message] => XYZ
[alert:accountExpired:heading] => XYZ
[alert:accountExpired:message] => XYZ
[alert:errorResponse:heading] => XYZ
[button:back] => XYZ
)
What I need to get is:
array() {
["alert"]=> array(7) {
["accountDisabled"]=> array(2) {
["heading"]=> string(3) "XYZ"
["message"]=> string(3) "XYZ" }
["accountExpired"]=> array(2) {
["heading"]=> string(3) "XYZ"
["message"]=> string(3) "XYZ" }
["clientError"]=> array(2) {
["heading"]=> string(3) "XYZ"
["message"]=> string(3) "XYZ" }
["errorResponse"]=> array(1) {
["heading"]=> string(3) "XYZ" }
}
["button"]=> array(1) {
["back"]=> string(3) "XYZ"
}
As I said this is a very small example, but the point is to get hierarchy from keys from array number one, hierarchy is divided by this character in key :
I checked for those questions that look similar to this one but they are not helpful lat all
How to access and manipulate multi-dimensional array by key names / path?
Using a string path to set nested array data
SO please read carefully the description of my issue.
I tried to use it for each loop, and I succeed to divide elements from the key, for one element, but I'm not sure where I need to store those hierarchy values for the next elements, any ideas?
$input = [
'alert:accountDisabled:heading' => 'XYZ_1',
'alert:accountDisabled:message' => 'XYZ_2',
'alert:accountExpired:heading' => 'XYZ_3',
'alert:accountExpired:message' => 'XYZ_4',
'alert:errorResponse:heading' => 'XYZ_5',
'button:back' => 'XYZ_6'
];
$results = [];
foreach ($input as $key => $value) {
$arr = explode(':', $key);
$result = $value;
for ($i = count($arr) - 1; $i >= 0; $i--) {
$result = [ $arr[$i] => $result ];
}
$results[] = $result;
}
$result = array_merge_recursive(...$results);
print_r($result);
Output:
Array
(
[alert] => Array
(
[accountDisabled] => Array
(
[heading] => XYZ_1
[message] => XYZ_2
)
[accountExpired] => Array
(
[heading] => XYZ_3
[message] => XYZ_4
)
[errorResponse] => Array
(
[heading] => XYZ_5
)
)
[button] => Array
(
[back] => XYZ_6
)
)
Based on Lukas.j answer, you can use this function:
function parsePath($array, $separator = ':'){
$result = [];
foreach($array as $key => $value){
if(strpos($key, $separator) !== FALSE){
$keys = explode($separator, $key);
$inner_result = $value;
foreach (array_reverse($keys) as $valueAsKey) $inner_result = [$valueAsKey => $inner_result];
$result[] = $inner_result;
}
}
return array_merge_recursive(...$result);
}

Php multiple array values to single array

For example
[Nationality_1] string(8)=>Indian [Nationality_5] string(12)=>American [Nationality_12] string(17)=>Japanese
I got these array values by foreach loop but I want to put these value to single array by index on strings
Desired output
[Nationality] [0] string(8)=>Indian [1] string(12)=>American[2]string(17)=>Japanese
I have tried array_values but output Null
I tried this but creates duplicate array in loop for multiple orders Please help me on it . Thanks
$Nationality[] = $value;
One solution is below code:
$nationality = array(
'Nationality_1' => 'Indian',
'Nationality_2' => 'American',
'Nationality_3' => 'Japanese'
);
$temp = array();
foreach ($nationality as $val) {
$temp[] = $val;
}
$nationality = $temp;
print_r($nationality);
unset($temp);
// Array ( [0] => Indian [1] => American [2] => Japanese )
It sounds like you may want to use array_values to pull all the nationalities from your input list.
array_values
Return all the values of an array
http://php.net/array_values
What you do with that is then up to you but from your desired output it seems you want them under another array with a "Nationality" key?
Here is an example...
$input = array(
'Nationality_1' => 'Indian',
'Nationality_5' => 'American',
'Nationality_12' => 'Japanese'
);
$output = array('Nationality' => array_values($input));
var_dump($output);
/*
array(1) {
["Nationality"]=>
array(3) {
[0]=>
string(6) "Indian"
[1]=>
string(8) "American"
[2]=>
string(8) "Japanese"
}
}
*/
See the code in action: https://eval.in/869938

How to update data if array is empty?

I want to update empty array .So I check is empty and want to update the original variable.So I tried by & but it doesn't change empty array $array2 .I had tried many hours but not working!!!
<?php
$array1 = array('one','two','three');
$array2 = array();
$array3 = array ('four');
$array4 = array ('five','six');
check([&$array1,&$array2,&$array3,&$array4]);
function check($arr){
foreach ($arr as $k=>$value) {
if(empty($value)){
$arr[$k][] = "nothing";
return $arr[$k];
}
else{
return $arr[$k];
}
}
}
var_dump($array2);
//actual output : empty
//expect output : 0 => string 'nothing'
?>
Have a look following code.
$array1 = array('one','two','three');
$array2 = array();
$array3 = array ('four');
$array4 = array ('five','six');
$arr11=check([&$array1,&$array2,&$array3,&$array4]);
function check($arr){
foreach ($arr as $k=>$value) {
print_r($value);
if(empty($value)){
$arr[$k] = "nothing";
}
else{
$arr[$k];
}
}
return $arr;
}
print_r($arr11);
var_dump($array2);
//actual output : empty
//expect output : 0 => string 'nothing'
It will display following result.
Array
(
[0] => Array
(
[0] => one
[1] => two
[2] => three
)
[1] => nothing
[2] => Array
(
[0] => four
)
[3] => Array
(
[0] => five
[1] => six
)
)
string(7) "nothing"
This will work for you:
<?php
$array1 = array('one','two','three');
$array2 = array();
$array3 = array ('four');
$array4 = array ('five','six');
list($array1, $array2, $array3, $array4) = check([$array1,$array2,$array3,$array4]);
function check($arr){
foreach ($arr as $k => $value) {
if(empty($value)){
$arr[$k] = "nothing";
}
}
return $arr;
}
var_dump($array2);
//actual output : string(7) "nothing"
//expect output : string(7) "nothing"
?>
You've written your function very strangely, actually.
UPDATE. Output of other arrays instead of only one.
var_dump($array1, $array2, $array3, $array4);
array(3) {
[0]=>
string(3) "one"
[1]=>
string(3) "two"
[2]=>
string(5) "three"
}
string(7) "nothing"
array(1) {
[0]=>
string(4) "four"
}
array(2) {
[0]=>
string(4) "five"
[1]=>
string(3) "six"
}

Create multidimensional array from flat file array

I have an array like this:
$arr = array(
'home.js' => new File(),
'view/index.html' => new File(),
'src/index.js' => new File(),
'src/libs/jquery.js' => new File()
);
Now I want to convert in a structure like this:
Array
(
[0] => Array
(
[text] => home.js
)
[1] => Array
(
[text] => view
[children] => Array
(
[0] => Array
(
[text] => index.html
)
)
)
[2] => Array
(
[text] => src
[children] => Array
(
[0] => Array
(
[text] => index.js
)
[1] => Array
(
[text] => libs
[children] => Array
(
[0] => Array
(
[text] => jquery.js
)
)
)
)
)
)
I tried for hours, with help of StackOverfow answers but I couldn't come up with a solution as all other questions have a different setup.
Edit:
What I got so far with the help of SO is (can't remember the exact answer though):
$out = array();
foreach($arr as $path => $file) {
$parts = explode('/', trim($path, '/'));
applyChain($out, $parts, $file);
}
function applyChain(&$arr, $parts, $value)
{
if (!is_array($parts)) {
return;
}
if (count($parts) == 0) {
$arr = $value;
} else {
array_shift($parts);
applyChain($arr[], $parts, $value);
}
}
print_r($out);
I don't know how exactly it works, especially the part applyChain($arr[] ...). It kinda works with the depth, but not with the file names. I get following output:
Array
(
[0] => File Object
(
)
[1] => Array
(
[0] => File Object
(
)
)
[2] => Array
(
[0] => File Object
(
)
)
[3] => Array
(
[0] => Array
(
[0] => File Object
(
)
)
)
)
There would be a solution in a few lines using explode() and eval(). But eval() is not considered clean, so lets try recursion:
<?php
class File {
}
$arr = array(
'home.js' => new File(),
'view/index.html' => new File(),
'src/index.js' => new File(),
'src/libs/jquery.js' => new File()
);
function sub($path) {
$rv = array();
$parts = explode('/', $path, 2); // strip off one level
$rv['text'] = $parts[0]; // put it into 'text' element
if (count($parts)>1) // is there anything left?
$rv['children'] = sub($parts[1]); // do the same for the rest of the path
return $rv;
}
$new = array();
foreach (array_keys($arr) as $file) {
$new[] = sub($file);
}
var_dump($new);
?>
But, as Peter commented, this creates seperate substructures even if the pathes have some part in common (like src/libs/jquery.js and src/libs/melon.js).
With the use of ugly eval() (which can be replaced later) I got the following code:
<?php
class File {
}
$arr = array(
'home.js' => new File(),
'view/index.html' => new File(),
'src/index.js' => new File(),
'src/libs/jquery.js' => new File(),
'src/libs/melon.js' => new File(),
);
// conversion
function sub($element) {
$rv = array();
foreach (array_keys($element) as $sub) {
$part['text'] = $sub;
if (is_array($element[$sub])) {
$part['children'] = sub($element[$sub]);
}
$rv[] = $part;
}
return $rv;
}
// create array with path file/folder names as keys
$new = array();
foreach (array_keys($arr) as $row) {
$def = '$new["'.preg_replace('&/&', '"]["', $row).'"] = 1;';
eval($def);
}
// run
$new2 = sub($new);
var_dump($new2);
?>
This outputs
array(3) {
[0]=>
array(1) {
["text"]=>
string(7) "home.js"
}
[1]=>
array(2) {
["text"]=>
string(4) "view"
["children"]=>
array(1) {
[0]=>
array(1) {
["text"]=>
string(10) "index.html"
}
}
}
[2]=>
array(2) {
["text"]=>
string(3) "src"
["children"]=>
array(2) {
[0]=>
array(1) {
["text"]=>
string(8) "index.js"
}
[1]=>
array(2) {
["text"]=>
string(4) "libs"
["children"]=>
array(2) {
[0]=>
array(1) {
["text"]=>
string(9) "jquery.js"
}
[1]=>
array(1) {
["text"]=>
string(8) "melon.js"
}
}
}
}
}
}

Combine pairs to groups [PHP / Arrays]

I have pairs of items in an PHP array. Example:
<?php
$elements = array(
'tiger'=>'lion',
'car'=>'bike',
'lion'=>'zoo',
'truck'=>'plane'
);
?>
Now I want to combine these items so that all items which are connected in any way go to one group. Continuation of the example above:
<?php
$groups = array(
0=>array('tiger', 'lion', 'zoo'),
1=>array('car', 'bike'),
2=>array('truck', 'plane'
);
?>
Is this understandable? How could I achieve this?
I'm looking for a function which does this.
<?php
$elements = array(
'tiger' => 'lion',
'car' => 'bike',
'lion' => 'zoo',
'truck' => 'plane'
);
$groups = array();
foreach ($elements as $key => $val) {
$appended = false;
foreach ($groups as &$group) {
if ($group[0] == $key) {
array_unshift($group, $val);
$appended = true;
break;
}
}
if (!$appended) {
$groups[] = array($val, $key);
}
}
var_dump($groups);
Gives:
array(3) {
[0]=>
array(3) {
[0]=>
string(3) "zoo"
[1]=>
string(4) "lion"
[2]=>
string(5) "tiger"
}
[1]=>
&array(2) {
[0]=>
string(4) "bike"
[1]=>
string(3) "car"
}
[2]=>
array(2) {
[0]=>
string(5) "plane"
[1]=>
string(5) "truck"
}
}
Here's an O(n) solution:
$elements = array(
'tiger' => 'lion',
'car' => 'bike',
'lion' => 'zoo',
'truck' => 'plane'
);
$groups = array();
$sub = array();
$ignore = array();
foreach ( $elements as $key=>$value ) {
if ( isset($ignore[$key]) ) {
continue;
}
$sub = array($key, $value);
if ( isset($elements[$value]) ) {
$ignore[$value] = 1;
$sub[] = $elements[$value];
}
$groups[] = $sub;
}
print_r($groups);
Result:
Array
(
[0] => Array
(
[0] => tiger
[1] => lion
[2] => zoo
)
[1] => Array
(
[0] => car
[1] => bike
)
[2] => Array
(
[0] => truck
[1] => plane
)
)
The idea is simple:
Create a new array to hold your groups
Loop over the item array
Check if the group for the item exists in the group array - if it does not, create it
Put item in group

Categories