How would you transform a monodimensional array into a multidimensional array in PHP? Suppose you have something like this
$array['breakfast'] = 'milk';
$array['meal.firstdish'] = 'pasta';
$array['meal.seconddish.maincourse'] = 'veal';
$array['meal.seconddish.dressing'] = 'fries';
$array['meal.dessert'] = 'pie';
And you want a function to transform it into
$array['breakfast'] = 'milk';
$array['meal']['firstdish'] = 'pasta';
$array['meal']['seconddish']['maincourse'] = 'veal';
$array['meal']['seconddish']['dressing'] = 'fries';
$array['meal']['dessert'] = 'pie';
The same function should of course transform
$tire['ean'] = '3286347717116';
$tire['brand.maker'] = 'BRIDGESTONE';
$tire['brand.model.name'] = 'POTENZA';
$tire['brand.model.variant'] = 'RE 040 RFT * SZ';
into
$tire['ean'] = '3286347717116';
$tire['brand']['maker'] = 'BRIDGESTONE';
$tire['brand']['model']['name'] = 'POTENZA';
$tire['brand']['model']['variant'] = 'RE 040 RFT * SZ';
I was thinking of using explode, then eval on the results, but eval always feels like cheating to me and I guess it would keep my code from running in HipHop.
The reason I want to do this is that I have to export lots of different tables from a database into XML files, and I already have a robust function that turns a multidimensional array into XML.
Like this:
function build(array &$trg, array $k,$key,$value) {
$p = &$trg;
while ( !empty($k) ) {
$nk = array_shift($k);
if ( !isset($p[$nk]) ) {
$p[$nk] = [];
}
$p = &$p[$nk];
}
$p[$key] = $value;
return $p;
}
$array['breakfast'] = 'milk';
$array['meal.firstdish'] = 'pasta';
$array['meal.seconddish.maincourse'] = 'veal';
$array['meal.seconddish.dressing'] = 'fries';
$array['meal.dessert'] = 'pie';
$out = [];
foreach ($array as $key => $value ) {
$path = explode('.',$key);
$last = array_pop($path);
build($out,$path,$last,$value);
}
print_r($out);
You were on the right track with explode, but there's no need to use eval. Once you've got the pieces of the keys available, you can loop over them and incrementally assign a pointer into a new array:
<?php
$array['breakfast'] = 'milk';
$array['meal.firstdish'] = 'pasta';
$array['meal.seconddish.maincourse'] = 'veal';
$array['meal.seconddish.dressing'] = 'fries';
$array['meal.dessert'] = 'pie';
$result = [];
$target = null;
foreach ($array as $key => $value) {
// Start by targeting the base of our resulting array
$target =& $result;
// Break the keys apart into pieces
$keyParts = explode('.', $key);
// Assign new target based on indexing into the result array one "piece" at a time
while ($part = array_shift($keyParts)) {
$target =& $target[$part];
}
// Finally, assign the value to our target
$target = $value;
}
See https://eval.in/625627
I need a function like this one:
function multi(){
$args = get_func_args();
$array = ????
return $array;
}
print_r(multi('foo','bar','baz',123));
// expected result: array([foo] => array([bar] => array([baz] => 123)))
I've answered multiple variations of this using a reference to build-up the array:
function multi() {
$path = func_get_args(); //get args
$value = array_pop($path); //get last arg for value
$result = array(); //define our result
$temp = &$result; //reference our result
//loop through args to create key
foreach($path as $key) {
//assign array as reference to and create new inner array
$temp =& $temp[$key];
}
$temp = $value; //set the value
return $result;
}
print_r(multi('foo','bar','baz',123));
This will also work:
function multi(){
$array = null;
$args = func_get_args();
while(count($args)>0) {
$last = array_pop($args);
$array = $array ? array($last=>$array) : $last;
}
return $array;
}
$data = multi('foo','bar','baz',123);
to update an existing value (no checks if items really exists)
function set_multi($val, &$target){
$args = array_slice(func_get_args(), 2);
while(count($args)>0) {
$first = array_shift($args);
$target = &$target[$first];
}
$target = $val;
}
set_multi(456, $data, 'foo', 'bar', 'baz');
if($stmt->execute()){
$user = $stmt->get_result();
while ($obj = $user->fetch_object()) {
$result[] = $obj;
}
}
$result1encoded = json_encode($result);
echo $result1encoded;
// [{"uId":"1","firstName":"John"}]
I used implode like this :
echo $result1encoded = implode(' ',$result1);
// expecting '[{"uId":"1","firstName":"John"}]'
But it says
Object of class stdClass could not be converted to string
You can use array_map("json_encode", $your_array) to first convert each element of the array to string, and then use implode to glue it together.
See this https://eval.in/141541
<?php
$a = array();
$a[0] = new stdClass();
$a[0]->uId = "1";
$a[0]->firstName = "John";
$a[1] = new stdClass();
$a[1]->uId = "2";
$a[1]->firstName = "Albert";
$b = array_map("json_encode", $a);
echo implode(' ', $b);
?>
To convert Array to String you can use serialize() method like this
$result1encoded = json_encode($result);
echo serialize($result1encoded);
Another Way to do is
$result1encoded = json_encode($result);
echo $result1 = implode(' ',$result1encoded);
|**Edited Part**|
Please go through flowing link hope it solves ur problem
Array to String Conversions
This question already has answers here:
How does PHP 'foreach' actually work?
(7 answers)
Closed 8 years ago.
Consider the code below:
<?php
$arr = array();
$arr['b'] = 'book';
foreach($arr as $key=>$val) {
print "key=>$key\n";
if(!isset($arr['a']))
$arr['a'] = 'apple';
}
?>
It is not displaying 'a'. How foreach works with hash-table(array), to traverse each element. If lists are implement why can't I add more at run time ?
Please don't tell me that I could do this task with numeric based index with help of counting.
Foreach copies structure of array before looping(read more), so you cannot change structure of array and wait for new elements inside loop. You could use while instead of foreach.
$arr = array();
$arr['b'] = 'book';
reset($arr);
while ($val = current($arr))
{
print "key=".key($arr).PHP_EOL;
if (!isset($arr['a']))
$arr['a'] = 'apple';
next($arr);
}
Or use ArrayIterator with foreach, because ArrayIterator is not an array.
$arr = array();
$arr['b'] = 'book';
$array_iterator = new ArrayIterator($arr);
foreach($array_iterator as $key=>$val) {
print "key=>$key\n";
if(!isset($array_iterator['a']))
$array_iterator['a'] = 'apple';
}
I think you need to store array element continue sly
Try
<?php
$arr = array();
$arr['b'] = 'book';
foreach($arr as $key=>$val) {
print "key=>$key\n";
if(!isset($arr['a']))
$arr['a'][] = 'apple';
}
print_r($arr);
?>
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.
http://cz2.php.net/manual/en/control-structures.foreach.php
Try this:
You will get values.
<?php
$arr = array();
$arr['b'] = 'book';
foreach($arr as $key=>$val) {
print "key=>$key\n";
if(!isset($arr['a']))
$arr['a'] = 'apple';
}
echo '<pre>';
print_r($arr);
?>
Output:
key=>b
<pre>Array
(
[b] => book
[a] => apple
)
If you want to check key exist or not in array use array_key_exists function
Eg:
<?php
$arr = array();
$arr['b'] = 'book';
print_r($arr); // prints Array ( [b] => book )
if(!array_key_exists("a",$arr))
$arr['a'] = 'apple';
print_r($arr); // prints Array ( [b] => book [a] => apple )
?>
If you want to use isset condition try like this:
$arr = array();
$arr['b'] = 'book';
$flag = 0;
foreach($arr as $key=>$val) {
print "key=>$key\n";
if(!isset($arr["a"]))
{
$flag = 1;
}
}
if(flag)
{
$arr['a'] = 'apple';
}
print_r($arr);
How about using for and realtime array_keys()?
<?php
$arr = array();
$arr['b'] = 'book';
for ($x=0;$x<count($arr); $x++) {
$keys = array_keys($arr);
$key = $keys[$x];
print "key=>$key\n";
if(!isset($arr['a']))
$arr['a'] = 'apple';
}
I have a web service to identify people and their functions from an external database that returns me a set of data if the login is successful. The data (that interests me right now) is separated in different strings as follow:
$groups="group1, group2, group3"
$functions="member, member, admin"
The first element of the string $groups corresponds to the first element of the $functions string.
We can have empty spots in the strings:
$groups="group1,, group3";
$functions="member,, admin";
What is the best way to combine them to obtain:
$usertype(
group1=>member,
group2=>member,
group3=>admin,
);
Then I plan to use array_search() to get the name of the group that corresponds to a function.
This is very trick especially when the first element is empty but here is a comprehensive solution
What you need is :
// Your Varriables
$groups = "group1,, group3";
$functions = "member,, admin";
// Break Into Array
$groups = explode(",", $groups);
$functions = explode(",", $functions);
// Combine both new Arrays and Output Result
$new = array_combine($groups, $functions);
print_r($new);
If you need to fix null values then :
Example :
// Your Varriables
$groups = "group1,, group3";
$functions = "member,, admin";
// Break Into Array
$groups = explode(",", $groups);
$functions = explode(",", $functions);
// Fix Null Values
$groups = fixNull($groups, true);
$functions = fixNull($functions);
// Combine both new Arrays and Output Result
$new = array_combine($groups, $functions);
print_r($new);
Output
Array
(
[group1] => member
[group2] => member
[group3] => admin
)
See Live DEMO
More Complex:
// Your Varriables
$groups = ",,, group3";
$functions = ",member,, admin";
// Fix Null Values
$groups = fixNull(explode(",", $groups), true);
$functions = fixNull(explode(",", $functions));
// Combine both new Arrays and Output Result
$new = array_combine($groups, $functions);
print_r($new);
Output
Array
(
[group4] => member
[group5] => member
[group6] => member
[group3] => admin
)
Live DEMO
Function Used
function fixNull($array, $inc = false) {
$ci = new CachingIterator(new ArrayIterator($array), CachingIterator::FULL_CACHE);
if ($inc) {
$next = array_filter($array);
$next = current($next);
$next ++;
} else {
$next = array_filter($array);
sort($next);
$next = end($next);
}
$next || $next = null;
$modified = array();
foreach($ci as $item) {
$modified[] = empty($item) ? trim($next) : trim($item);
if (! $ci->getInnerIterator()->current()) {
$item || $item = $next;
$next = $inc ? ++ $item : $item;
}
}
return $modified;
}
$groups = explode(",", $groups);
$functions = explode(",", $functions);
//then use the elements of the $groups array as key and the elements of the $functions array as the value
$merged = array_combine($groups, $functions);
Something along the lines of this should help:
$usertype = array_combine(explode(',', $groups), explode(',', $functions));
Use explode() to make arrays of your strings, and array_combine() to use one array as keys, the other one as values.
$groups = "group1, group2, group3";
$functions = "member, member, admin";
$usertype = array_combine(explode(", ", $groups), explode(", ", $functions));
Have you tried a explode($delimiter , $string) and then filter the array? I think that would be a good way of doing it:
$groups="group1,, group3";
$functions="member,, admin";
$groups_array = array_map('trim',explode(',', $groups));
$functions_array = array_map('trim',explode(',', $functions));
$final = array();
for ($i = 0; $i <= count($groups_array); $i++) {
$final[$groups_array[$i]] = $functions_array[$i];
}
$merged = array_combine($groups_array, $functions_array);
Demo
$groups="group1, group2, group3"
$functions="member, member, admin"
preg_match_all('/\w+/', $groups, $groups);
preg_match_all('/\d+/', $functions, $functions);
$final = array();
foreach ($groups[0] AS $key => $letter)
$final[] = $letter . '=>' . $functions[0][$key];
echo join(', ', $final);
explode and array_combine.
Note that you have a problem with whitespaces. Therefore use the following:
<?php
$groups="group1, group2, group3";
$functions="member, member, admin";
$groupArray = array_map(function($element){return trim($element);},
explode(',',$groups)); // split into array and remove leading and ending whitespaces
$functionArray = array_map(function($element){return trim($element);},
explode(',',$functions)); // split into array and remove leading and ending whitespaces
print_r(array_combine($groupArray,$functionArray));
?>
This will output:
Array
(
[group1] => member
[group2] => member
[group3] => admin
)
EDIT: removed trim for the possibility that the first element is empty.