I need to create array like that:
Array('firstkey' => Array('secondkey' => Array('nkey' => ...)))
From this:
firstkey.secondkey.nkey.(...)
$yourString = 'firstkey.secondkey.nkey';
// split the string into pieces
$pieces = explode('.', $yourString);
$result = array();
// $current is a reference to the array in which new elements should be added
$current = &$result;
foreach($pieces as $key){
// add an empty array to the current array
$current[ $key ] = array();
// descend into the new array
$current = &$current[ $key ];
}
//$result contains the array you want
My take on this:
<?php
$theString = "var1.var2.var3.var4";
$theArray = explode(".", $theString); // explode the string into an array, split by "."
$result = array();
$current = &$result; // $current is a reference to the array we want to put a new key into, shifting further up the tree every time we add an array.
while ($key = array_shift($theArray)){ // array_shift() removes the first element of the array, and assigns it to $key. The loop will stop as soon as there are no more items in $theArray.
$current[$key] = array(); // add the new key => value pair
$current = &$current[$key]; // set the reference point to the newly created array.
}
var_dump($result);
?>
With an array_push() in the while loop.
What do you want the value of the deepest key to be?
Try something like:
function dotToArray() {
$result = array();
$keys = explode(".", $str);
while (count($keys) > 0) {
$current = array_pop($keys);
$result = array($current=>$result);
}
return $result;
}
Related
CASE:
I'm trying to get ordered items and quantity from another page, so I'm passing it using GET (http://foo.bar/?view=process-order&itm=1&qty=1000...), then I must to take this parameters and convert to an multidimensional array following this sequence:
EXPECTED:
URL will be: http://foo.bar/?view=foo-bar&itm=1&qty=1000&itm=2&qty=3000&itm=3&qty=1850
[0]=>
[itm]=>'1',
[qty]=>'1000',
[1]=>
[itm]=>'2',
[qty]=>'3000',
[2]=>
[itm]=>'3';
[qty]=>'1850',
etc.
CODE:
$url = $_SERVER['REQUEST_URI']; //get the URL
$items = parse_url($url, PHP_URL_QUERY); //get only the query from URL
$items = explode( '&', $items );//Explode array and remove the &
unset($items[0]); //Remove view request from array
$items = implode(",", $items); //Implode to a string and separate with commas
list($key,$val) = explode(',',$items); //Explode and remove the commas
$items = array($key => $val); //Rebuild array
ACTUAL RESULT:
[itm=1] => [qty=1000]
ACTUAL BEHAVIOUR:
Result leave only the first element in the array and make it like array({[itm=1]=>[qty=1000]}) that anyway isn't what I need.
Even If I've read much pages of PHP docs can't find the solution.
Thanks to all who can help
Your statement list($key,$val) = explode(',',$items); will only fetch the first two items in an array.
Here's a rewritten version
$chunks = explode('&', $_SERVER['QUERY_STRING']);
$items = array();
$current = -1; // so that entries start at 0
foreach ($chunks as $chunk) {
$parts = explode('=', $chunk);
if ($parts[0] == 'itm') {
$current++;
$items[$current]['itm'] = urldecode($parts[1]);
}
elseif ($parts[0] == 'qty') {
$items[$current]['qty'] = urldecode($parts[1]);
}
}
print_r($items);
Here is another version. I only modified the bottom part of your code (first 4 lines are untouched).
$url = $_SERVER['REQUEST_URI']; //get the URL
$items = parse_url($url, PHP_URL_QUERY); //get only the query from URL
$items = explode('&', $items );//Explode array and remove the &
unset($items[0]); //Remove view request from array
$list = array(); // create blank array for storing data
foreach ($items as $item){
list($key, $val) = explode('=', $item);
if ($key === 'itm')
$list[] = ['itm' => $val];
else // qty
$list[count($list) - 1]['qty'] = $val;
}
Hope this helps.
I can't seem to figure this out and I'm hoping someone has a magical recursive solution to this. I have a list of keys and basically I want to transform it into a nested array.
array('level1', 'level2', 'level3');
To
array(
'level1' => array(
'level2' => array(
'level3' // last key in array should be just a value
)
)
)
Much appreciation to anyone who can help!
Something like this should do the job:
function buildMultiDimensional(Array $arr)
{
// the first value will become a new key
$newKey = array_shift($arr);
if (empty($arr)) {
// this is where the recursion stops
return $newKey;
}
// and the recursion !!!
return array($newKey => buildMultiDimensional($arr));
}
$arr = array('level1', 'level2', 'level3', 'level4', 'level5');
var_dump(buildMultiDimensional($arr));
The result is what's expected:
array(1) {
["level1"]=>
array(1) {
["level2"]=>
array(1) {
["level3"]=>
array(1) {
["level4"]=>
string(6) "level5"
}
}
}
}
You don't need recursion. A single loop is fine with references.
<?php
//array to iterate
$array = array('level1', 'level2', 'level3');
//contains our entire array
$out = array();
//temp variable to store references as we go down.
$tmp = &$out;
//get the last value off the array
$last = array_pop($array);
//loop over the array
foreach($array as $level){
//make an array under the current level
$tmp[$level] = array();
//assign tmp to the new level
$tmp = &$tmp[$level];
}
//assign the last key as the value under the last key
$tmp = $last;
//display output
print_r($out);
example: http://codepad.viper-7.com/zATfyo
And without references, working in reverse:
<?php
//array to iterate
$array = array('level1', 'level2', 'level3');
//get the last value off the array
$out = array_pop($array);
//flip the array backwards
$array = array_reverse($array);
//loop over the array
foreach($array as $level){
$out = array($level=>$out);
}
//display output
print_r($out);
Example: http://codepad.viper-7.com/fgxeHO
I'm having trouble finding a solution to the following problem.
I need to take the first value of one array ($split), find it in another array ($array) and return a corresponding value into a new array ($matched), then loop until all values in $split have been matched and returned (in order) to $matched.
I've annotated my code below to explain further.
<?php
$split = explode('/', '1/2/3');
// $split can be any length and any order
// EG. $split = explode('/', '1/2/3/66/4/9');
$result = $connection->query("SELECT id, filename FROM pages");
while ($row = $result->fetch_array()) {
$new_array[$row['id']] = $row;
}
foreach($new_array as $array) {
// take first value from $split
// match value with 'id' of $array
// return corresponding 'filename'
// set as first value of $matched
$matched = //
// loop until all values from $split have been matched
// and the corresponding filename has been added to $matched.
}
$join = implode('/', $matched); // join $matched as string.
?>
Let'see:
You have list of numbers (ids),
you have map: id -> filename,
you need filenames ( imploded by slash )
so:
<?php
// $split can be any length and any order
// EG. $split = explode('/', '1/2/3/66/4/9');
$split = explode('/', '1/2/3');
// NB!
$split = array_flip( $split );
$result = $connection->query("SELECT id, filename FROM pages");
/* I need exactly map id -> filename for implode() */
while ($row = $result->fetch_assoc()) {
$new_array[$row['id']] = $row['filename'];
}
$matched = array_intersect_key($new_array, $split);
$join = implode('/', $matched); // join $matched as string.
?>
Try the following example:
// ... some code
$matched = array();
foreach ( $split AS $key ) {
if ( isset($array[$key]) ) {
$matched[] = $array[$key];
}
}
return $matched;
// ... more code
I would build a mysql query this way:
SELECT id, filename FROM pages WHERE id IN(1,2,3,66,4,9) ORDER BY FIELD(id,1,2,3,66,4,9)
And then, in php:
while($row = $result->fetch_assoc()) {
$match[] = $row;
}
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.
I have a string I would like to separate and make a multidimensional array out of. The string looks like this:
$string = "item-size:large,color:blue,material:cotton,item-size:medium,color:red,material:silk,";
Unfortunately, I have no control over how the string is put together, which is why I'm trying to make this array.
My goal is to make an array like this:
$item[1]['color'] // = blue
$item[2]['material'] // = silk
So, here's what I've done:
$item = array();
$i=0; // I know this is messy
$eachitem = explode("item-",$string);
array_shift($eachitem); // get rid of the first empty item
foreach ($eachitem as $values) {
$i++; // Again, very messy
$eachvalue = explode(",",$values);
array_pop($eachvalue); // get rid of the last comma before each new item
foreach ($eachvalue as $key => $value) {
$item[$i][$key] = $value;
}
}
I'm obviously lost with this... any suggestions?
You're mostly there. Just replace your inner foreach with
foreach ($eachvalue as $value) {
$properties = explode(':', $value);
$item[$i][$properties[0]] = $properties[1];
}
You're close, this is how I would do it:
$string = "item-size:large,color:blue,material:cotton,item-size:medium,color:red,material:silk,";
$substr = explode("item-", $string);
$items = array();
foreach ($substr as $string) {
$subitems = array();
$pairs = explode(",", $string);
foreach ($pairs as $pair) {
list($key, $value) = explode(":", $pair, 2);
$subitems[$key] = $value;
}
$items[] = $subitems;
}
var_dump($items);
Using list here is great :) Do note that you would need the extra count limiter in explode else you might lose data if there are more :.
$array = array();
$string = explode(',', $string);
foreach($string as $part):
$part = trim($part);
if(strlen($part) < 3) continue;
$part = explode(':', $part);
$array[$part[0]] = $part[1];
endforeach;
$string = "item-size:large,color:blue,material:cotton,item-size:medium,color:red,material:silk,";
$num_attr = 3;
$item = array();
$i=$x=0;
foreach(explode(',', trim($string,',')) as $attr)
{
list($key, $value) = explode(':', $attr);
$item[$x+=($i%$num_attr==0?1:0)][$key] = $value;
$i++;
}
Set the $num_attr to the number of item attributes in the string (this will allow adjustments in the future if they grow/shrink). The trim inside the foreach is removing ay "empty" data like the last comma (it will also remove a empty first comma if one ever shows up). The crazy looking $item[$x+=($i%$num_attr==0?1:0)] is taking the modulus of the counter / number of attributes which when it is 0 that means we are on a new product line so we add 1 to x which populates the item number index, if the modulus returns a number then we know we are on the same product so we add 0 which doesn't change the items index so that attribute is added on to the same item.