Expand "dot notation" keys in a nested array to child arrays - php

I start with a nested array of some arbitrary depth. Within that array, some keys are a series of tokens separated by dots. For example "billingAddress.street" or "foo.bar.baz". I would like to expand those keyed elements to arrays, so the result is a nested array with all those keys expanded.
For example:
[
'billingAddress.street' => 'My Street',
'foo.bar.baz' => 'biz',
]
should be expanded to:
[
'billingAddress' => [
'street' => 'My Street',
],
'foo' => [
'bar' => [
'baz' => 'biz',
]
]
]
The original "billingAddress.street" can be left alongside the new "billingAddress" array, but it does not need to be (so the solution may operate on the original array or create a new array). Other elements such as "billingAddress.city" may need to be added to the same expanded portion of the array.
Some keys may have more than two tokens separated by dots, so will need to be expanded deeper.
I've looked at array_walk_recursive() but that only operates on elements. For each matching element key, I actually want to modify the parent array those elements are in.
I've looked at array_map, but that does not provide access to the keys, and as far as I know is not recursive.
An example array to expand:
[
'name' => 'Name',
'address.city' => 'City',
'address.street' => 'Street',
'card' => [
'type' => 'visa',
'details.last4' => '1234',
],
]
This is to be expanded to:
[
'name' => 'Name',
'address.city' => 'City', // Optional
'address' => [
'city' => 'City',
'street' => 'Street',
],
'address.street' => 'Street', // Optional
'card' => [
'type' => 'visa',
'details.last4' => '1234', // Optional
'details' => [
'last4' => '1234',
],
],
]
What I think I need, is something that walks to each array in the nested array and can apply a user function to it. But I do suspect I'm missing something obvious. The payment gateway I am working with sends me this mix of arrays and "pretend arrays" using the dot-notation, and my objective is to normalize it into an array for extracting portions.
I believe the problem differs from similar questions on SO due to this mix of arrays and non-arrays for expanding. Conceptually it is a nested array where sound groups of elements at any level need to be replaced with new arrays, so there are two levels of recursion happening here: the tree walking, and the expansion, and then the walking of the expanded trees to see if there is more expansion needed.

You could find it useful to reverse the order of the keys you get from exploding the combined (dotted) key. In that reversed order it is easier to progressively wrap a previous result into a new array, thereby creating the nested result for one dotted key/value pair.
Finally, that partial result can be merged into the accumulated "grand" result with the built-in array_merge_recursive function:
function expandKeys($arr) {
$result = [];
foreach($arr as $key => $value) {
if (is_array($value)) $value = expandKeys($value);
foreach(array_reverse(explode(".", $key)) as $key) $value = [$key => $value];
$result = array_merge_recursive($result, $value);
}
return $result;
}
See it run on repl.it

Here's a recursive attempt. Note that this doesn't delete old keys, doesn't maintain any key ordering and ignores keys of the type foo.bar.baz.
function expand(&$data) {
if (is_array($data)) {
foreach ($data as $k => $v) {
$e = explode(".", $k);
if (count($e) == 2) {
[$a, $b] = $e;
$data[$a][$b]= $v;
}
expand($data[$k]);
}
}
}
Result:
Array
(
[name] => Name
[address.city] => City
[address.street] => Street
[card] => Array
(
[type] => visa
[details.last4] => 1234
[details] => Array
(
[last4] => 1234
)
)
[address] => Array
(
[city] => City
[street] => Street
)
)
Explanation:
On any call of the function, if the parameter is an array, iterate through the keys and values looking for keys with a . in them. For any such keys, expand them out. Recursively call this function on all keys in the array.
Full version:
Here's a full version that supports multiple .s and cleans up keys afterwards:
function expand(&$data) {
if (is_array($data)) {
foreach ($data as $k => $v) {
$e = explode(".", $k);
$a = array_shift($e);
if (count($e) == 1) {
$data[$a][$e[0]] = $v;
}
else if (count($e) > 1) {
$data[$a][implode(".", $e)] = $v;
}
}
foreach ($data as $k => $v) {
expand($data[$k]);
if (preg_match('/\./', $k)) {
unset($data[$k]);
}
}
}
}

Another solution by #trincot has been accepted as being more elegant, and is the solution I am using now.
Here is my solution, which expands on the solution and tips given by #ggorlen
The approach I have taken is:
Create a new array rather than operate on the initial array.
No need to keep the old pre-expanded elements. They can be added easily if needed.
Expanding the keys is done one level at a time, from the root array, with the remaining expansions passed back in recursively.
The class method:
protected function expandKeys($arr)
{
$result = [];
while (count($arr)) {
// Shift the first element off the array - both key and value.
// We are treating this like a stack of elements to work through,
// and some new elements may be added to the stack as we go.
$value = reset($arr);
$key = key($arr);
unset($arr[$key]);
if (strpos($key, '.') !== false) {
list($base, $ext) = explode('.', $key, 2);
if (! array_key_exists($base, $arr)) {
// This will be another array element on the end of the
// arr stack, to recurse into.
$arr[$base] = [];
}
// Add the value nested one level in.
// Value at $arr['bar.baz.biz'] is now at $arr['bar']['baz.biz']
// We may also add to this element before we get to processing it,
// for example $arr['bar.baz.bam']
$arr[$base][$ext] = $value;
} elseif (is_array($value)) {
// We already have an array value, so give the value
// the same treatment in case any keys need expanding further.
$result[$key] = $this->expandKeys($value);
} else {
// A scalar value with no expandable key.
$result[$key] = $value;
}
}
return $result;
}
$result = $this->expandKeys($sourceArray)

Related

Check if array doesn't have a key and create it dynamically

I need to check if the keys of an array match an array of keys, and if they don't match then they need to be created. While I managed to create the check I still need to return all keys that don't match in the in_array condition so that they can be added to the original array. How can I achieve this?
My current code:
$new_value = ['id','name','age'];
$keys = ['id','name','age','sex','height','weight'];
foreach($new_value as $new_value){
if(!in_array($new_value, $keys )){
$new_value["{$key}"] = '';
}
}
The desired result would be:
Array pre processing:
'id' => 1,
'name' => 'Ed',
'age' => 15,
Array post processing:
'id' => 1,
'name' => 'Ed',
'age' => 15,
'sex' => '',
'height' => '',
'weight' => '',
So, there are a couple of things here.
// When you are running through your foreach, you don't want to overwrite your
// array variable with the value, which is what is happening. Switch this to `new_values` (plural)
$new_values = ['id','name','age'];
$keys = ['id','name', 'age','sex','height','weight'];
// Since $keys is your desired structure, we want to loop through $key rather than $new_values, and add any missing keys to the $new_values
foreach($keys as $key){
// We want to check if $new_values has all the $keys (you were checking if $keys had all of $new_values, which it does already
if(!in_array($key, $new_values )){
// Since $key is already a string, we don't need to place it in quotes, just put the variable directly into the array as a new array item (because you are using an array of strings, the keys will be numerical)
$new_values[] = $key
}
}
If you are looking for a keyed array, so that you can get the value of $new_values['name'], then you will need to set your arrays up differently and do your checks differently. You can also use $keys to hold a default value.
// Set the keys for your array, instead of having an array of strings that is keyed numerically
$new_values = ['id' => 'user_id','name' => 'user name','age' => 'user age'];
$keys = ['id' => 'default_value','name' => 'default_value', 'age' => 'default_value','sex' => 'default_value','height' => 'default_value','weight' => 'default_value'];
// Here we'll get the key and value of each item in the $keys array
foreach($keys as $key => $default) {
// Check if the array key exists in new values and if not, set it to the predefined default value
if(!array_key_exists($key, $new_values) {
$new_values[$key] = $default;
}
}
EDIT
As per one of the comments on the answer, you could further simplify this with array_merge. If you want to throw an error or do something special on each field, you could use the loop. If you just want to fill in the blanks, it would work like:
// Set the keys for your array, instead of having an array of strings that is keyed numerically
$new_values = ['id' => 'user_id','name' => 'user name','age' => 'user age'];
$keys = ['id' => 'default_value','name' => 'default_value', 'age' => 'default_value','sex' => 'default_value','height' => 'default_value','weight' => 'default_value'];
// If you aren't going to be using the original $new_values array for anything, you can just overwrite it.
// As stated in the comment below, $new_values should be the second value, keys that are in both arrays will be overwritten by what's in the second array.
$new_values = array_merge($keys, $new_values);
// If you will be using the original $new_values array later in the code, you can set the output to a new variable
$filled_values = array_merge($keys, $new_values);
I'm not sure, but you can try next code:
<?php
$data = [
"id" => 1,
"name" => "Ed",
"age" => 15,
];
$keys = ["id", "name", "age", "sex", "height", "weight"];
$result = array_reduce(
$keys,
function ($data, $key) {
if (!isset($data[$key])) $data[$key] = '';
return $data;
},
$data
);
var_export($result);
PHP sandbox here

PHP Compare and change certain elements in multidimensional arrays

To be short, I have two simple arrays and I want to verify if certain keys from the second array have empty values and replace them with their correspondent values from the first array.
Example:
$a1 = [ 1 => 'one', 2 => 'two', 3 => 'three',5=>'cinco', 6=>'six'];
$a2 = [ 2 => 'two', 5=>'five', 6=>'' ];
Result:
Array
(
[2] => two
[5] => five
[6] => six
)
The following code works already for this.
$keys = array_keys($a1);
foreach ($keys as $k)
{
if ((isset($a2[$k])) && (($a2[$k]) == '')) {
$a2[$k] = $a1[$k];
}
}
print_r($a2);
But what if we want to apply this for two 2D arrays? What will be the proper approach in that case? Let's say these two 2D arrays will be:
$superheroes_complete = array(
"spiderman" => array(
"name" => "Peter Parker",
"email" => "peterparker#mail.com",
),
"superman" => array(
"name" => "Clark Kent",
"email" => "clarkkent#mail.com",
),
"ironman" => array(
"name" => "Harry Potter",
"email" => "harrypotter#mail.com",
)
);
$superheroes_empty = array(
"spiderman" => array(
"name" => "Peter Parker",
"email" => "",
),
"superman" => array(
"name" => "Clark Kent",
"email" => "something",
),
"ironman" => array(
"name" => "Harry Potter",
"email" => "another one",
)
);
Expectation:
$superheroes = array(
"spider-man" => array(
"name" => "Peter Parker",
"email" => "peterparker#mail.com",
),
"super-man" => array(
"name" => "Clark Kent",
"email" => "something",
),
"iron-man" => array(
"name" => "Harry Potter",
"email" => "another one",
)
);
Much appreciation and thank you in advance!
You've added another level to your data, so you can just add another level to your checking as well with a second foreach loop:
foreach ($superheroes_complete as $hero => $info) {
foreach ($info as $key => $value) {
if (empty($superheroes_empty[$hero][$key])) {
$superheroes_empty[$hero][$key] = $value;
}
}
}
First note that your 1D case can be simplified:
foreach ($a2 as $k => $v) {
if (!isset($v)) {
$a2[$k] = $a1[$k];
}
}
Then for the 2D case, assuming the 1st level keys are always the same (or it becomes a quite different question!):
foreach ($superheroes_complete as $main_k => $main_v) {
foreach ($main_v as $k => $v) {
if (!isset($v)) {
$superheroes_empty[$main_k][$k] = $superheroes_complete[$main_k][$k];
}
}
If you only need to take care of the "email" field you can do this :
<?php
$keys = array_keys($superheroes_complete);
foreach ($keys as $k)
{
if ((isset($superheroes_empty[$k]["email"])) &&
(($superheroes_empty[$k]["email"]) == '')) {
$superheroes_empty[$k]["email"] = $superheroes_complete[$k]["email"];
}
}
var_dump($superheroes_empty);
?>
For the generic case where the depth of nesting is unlimited, you could use this recursive function:
function fillEmpty(&$filled, &$empty) { // arguments are by reference
if ($empty === "") {
$empty = $filled;
return;
}
if (!is_array($filled) || !is_array($empty)) return;
foreach ($filled as $key => $value) {
if (isset($empty[$key])) fillEmpty($value, $empty[$key]);
}
}
Example call:
fillEmpty($superheroes_complete, $superheroes_empty);
This modifies the second argument, filling the empty values.
See it run on eval.in
It might be your lucky day, php has some built in functions to compare arrays values and keys. Use array_diff() which can compare two or more arrays and return the difference. You could also use array_intersect() which does the opposite.
If you want to only compare the keys, use array_diff_key()which returns only the key difference or array_intersect_key() which returns the matched keys.
You could also consider a recursive solution. This could work on both the 1D and 2D arrays, or even an array of N dimensions.
I'm aware that recursion should be used with care, as it can be quite resource intensive. This is however a more versatile solution, and keeps the code cleaner with less nested control structures and early returns, which I find better readable. I'll use the native array_walk method because I was taught that it should perform better then a php loop.
So this is what my code would look like:
function array_complement_recursive(&$partial, $complete) {
array_walk($partial, function(&$value, $key) use ($complete) {
// (for safety) complete does not contain matching key: done
if (! array_key_exists($key, $complete)) {
return;
}
// value is array: call recursive
if (is_array($value)) {
array_complement_recursive($value, $complete[$key]);
return;
}
// value is not 'empty': done
// note that null, 0, false will also not match, you may want to make
// this check more specific to match only the empty string
if ($value) {
return;
}
$value = $complete[$key];
});
}
I've set up a little demo so you can see that it works on both your examples. And as I said, it should even work for arrays with more dimensions, or a more irregular structure.
http://phpfiddle.org/main/code/49iz-vrwg
I've added some comments to explain, but feel free to ask if anything is unclear.

Transform flat array to tree with one-time loop

SO,
The problem
Suppose we have flat array with following structure:
$array = [
['level'=>1, 'name' => 'Root #1'],
['level'=>1, 'name' => 'Root #2'],
['level'=>2, 'name' => 'subroot 2-1'],
['level'=>3, 'name' => '__subroot 2-1/1'],
['level'=>2, 'name' => 'subroot 2-2'],
['level'=>1, 'name' => 'Root #3']
];
The issue is - transform that array so it will became a tree. Subordination is determined only with elements order and level field. Let's define children as a name of dimension for storing child nodes. For array above that will be:
array (
array (
'level' => 1,
'name' => 'Root #1',
),
array (
'level' => 1,
'name' => 'Root #2',
'children' =>
array (
array (
'level' => 2,
'name' => 'subroot 2-1',
'children' =>
array (
array (
'level' => 3,
'name' => '__subroot 2-1/1',
),
),
),
array (
'level' => 2,
'name' => 'subroot 2-2',
),
),
),
array (
'level' => 1,
'name' => 'Root #3',
),
)
A little more clarifications, if it's not obvious who is parent for who: following code could easily visualize idea:
function visualize($array)
{
foreach($array as $item)
{
echo(str_repeat('-', $item['level']).'['.$item['name'].']'.PHP_EOL);
}
}
visualize($array);
-for array above it's:
-[Root #1]
-[Root #2]
--[subroot 2-1]
---[__subroot 2-1/1]
--[subroot 2-2]
-[Root #3]
Specifics
There are some restrictions both for desired solution and input array:
Input array is always valid: that means it's structure can always be refactored to tree structure. No such weird things as negative/non-numeric levels, no invalid levels structure, e t.c.
Input array can be huge and, currently, maximum level is not restricted
Solution must resolve a matter with single loop, so we can not split array to chunks, apply recursion or jump within array somehow. Just simple foreach (or another loop - it does not matter), only once, each element one-by-one should be handled.
My approach
Currently, I have solution with stack. I'm working with references and maintaining current element of stack to which writing will be done at current step. That is:
function getTree(&$array)
{
$level = 0;
$tree = [];
$stack = [&$tree];
foreach($array as $item)
{
if($item['level']>$level) //expand stack for new items
{
//if there are child elements, add last to stack:
$top = key($stack);
if(count($stack[$top]))
{
end($stack[$top]);
$stack[] = &$stack[$top][key($stack[$top])];
}
//add ['children'] dim to top stack element
end($stack);
$top = key($stack);
$stack[$top]['children'] = [];
$stack[] = &$stack[$top]['children'];
}
while($item['level']<$level--) //pop till certain level
{
//two times: one for last pointer, one for ['children'] dim
array_pop($stack);
array_pop($stack);
}
//add item to stack top:
end($stack);
$stack[key($stack)][] = $item;
$level = $item['level'];
}
return $tree;
}
-since it's long enough, I've created a sample of usage & output.
The question
As you can see, my solution is quite long and it relies on references & array internal pointer handling (such things as end()), so the question is:
May be there are other - shorter and clearer ways to resolve this issue? It looks like some standard question, but I've not found any corresponding solution (there is one similar question - but there OP has exact parent_id subordination while I have not)
The good thing about your problem is that your input is always formatted properly so your actual problem is narrowed down to finding children for each node if they exist or finding parent for each node if it has one. The latter one is more suitable here, because we know that node has parent if its level is more than one and it is the nearest node above it in initial flat array with level that equals level of current node minus one. According to this we can just keep track on few nodes that we are interested in. To be more exact whenever we find two nodes with the same level, the node that was found earlier can't have more children.
Implementation of this will look like this:
function buildTree(array &$nodes) {
$activeNodes = [];
foreach ($nodes as $index => &$node) {
//remove if you don't want empty ['children'] dim for nodes without childs
$node['children'] = [];
$level = $node['level'];
$activeNodes[$level] = &$node;
if ($level > 1) {
$activeNodes[$level - 1]['children'][] = &$node;
unset($nodes[$index]);
}
}
}
Demo
The implementation with using recursion:
function buildTreeHelper(&$array, $currentLevel = 1)
{
$result = array();
$lastIndex = 0;
while($pair = each($array)) {
list(, $row) = $pair;
$level = $row['level'];
if ($level > $currentLevel) {
$result[$lastIndex]['children'] = buildTreeHelper($array, $level);
} else if ($level == $currentLevel) {
$result[++$lastIndex] = $row;
} else {
prev($array); // shift back
break;
}
}
return $result;
}
function buildTree($array)
{
reset($array);
return buildTreeHelper($array);
}
$array = [
['level'=>1, 'name' => 'Root #1'],
['level'=>1, 'name' => 'Root #2'],
['level'=>2, 'name' => 'subroot 2-1'],
['level'=>3, 'name' => '__subroot 2-1/1'],
['level'=>2, 'name' => 'subroot 2-2'],
['level'=>1, 'name' => 'Root #3']
];
print_r(buildTree($array));

PHP array unset string

I am trying to unset a group of array keys that have the same prefix. I can't seem to get this to work.
foreach ($array as $key => $value) {
unset($array['prefix_' . $key]);
}
How can I get unset to see ['prefix_' . $key] as the actual variable? Thanks
UPDATE: The $array keys will have two keys with the same name. Just one will have the prefix and there are about 5 keys with prefixed keys:
Array {
[name] => name
[prefix_name] => other name
}
I don't want to remove [name] just [prefix_name] from the array.
This works:
$array = array(
'aa' => 'other value aa',
'prefix_aa' => 'value aa',
'bb' => 'other value bb',
'prefix_bb' => 'value bb'
);
$prefix = 'prefix_';
foreach ($array as $key => $value) {
if (substr($key, 0, strlen($prefix)) == $prefix) {
unset($array[$key]);
}
}
If you copy/paste this code at a site like http://writecodeonline.com/php/, you can see for yourself that it works.
You can't use a foreach because it's only a copy of the collection. You'd need to use a for or grab the keys separately and separate your processing from the array you want to manipulate. Something like:
foreach (array_keys($array) as $keyName){
if (strncmp($keyName,'prefix_',7) === 0){
unset($array[$keyName]);
}
}
You're also already iterating over the collection getting every key. Unless you had:
$array = array(
'foo' => 1,
'prefix_foo' => 1
);
(Where every key also has a matching key with "prefix_" in front of it) you'll run in to trouble.
I'm not sure I understand your question, but if you are trying to unset all the keys with a specific prefix, you can iterate through the array and just unset the ones that match the prefix.
Something like:
<?php
foreach ($array as $key => $value) { // loop through keys
if (preg_match('/^prefix_/', $key)) { // if the key stars with 'prefix_'
unset($array[$key]); // unset it
}
}
You're looping over the array keys already, so if you've got
$array = (
'prefix_a' => 'b',
'prefix_c' => 'd'
etc...
)
Then $keys will be prefix_a, prefix_c, etc... What you're doing is generating an entirely NEW key, which'd be prefix_prefix_a, prefix_prefix_c, etc...
Unless you're doing something more complicated, you could just replace the whole loop with
$array = array();
I believe this should work:
foreach ($array as $key => $value) {
unset($array['prefix_' . str_replace('prefix_', '', $key]);
}

PHP Change Array Keys

Is there a way to change all the numeric keys to "Name" without looping through the array (so a php function)?
[
0 => 'blabla',
1 => 'blabla',
2 => 'blblll',
// etc ...
]
If you have an array of keys that you want to use then use array_combine
Given $keys = array('a', 'b', 'c', ...) and your array, $list, then do this:
$list = array_combine($keys, array_values($list));
List will now be array('a' => 'blabla 1', ...) etc.
You have to use array_values to extract just the values from the array and not the old, numeric, keys.
That's nice and simple looking but array_values makes an entire copy of the array so you could have space issues. All we're doing here is letting php do the looping for us, not eliminate the loop. I'd be tempted to do something more like:
foreach ($list as $k => $v) {
unset ($list[$k]);
$new_key = *some logic here*
$list[$new_key] = $v;
}
I don't think it's all that more efficient than the first code but it provides more control and won't have issues with the length of the arrays.
No, there is not, for starters, it is impossible to have an array with elements sharing the same key
$x =array();
$x['foo'] = 'bar' ;
$x['foo'] = 'baz' ; #replaces 'bar'
Secondarily, if you wish to merely prefix the numbers so that
$x[0] --> $x['foo_0']
That is computationally implausible to do without looping. No php functions presently exist for the task of "key-prefixing", and the closest thing is "extract" which will prefix numeric keys prior to making them variables.
The very simplest way is this:
function rekey( $input , $prefix ) {
$out = array();
foreach( $input as $i => $v ) {
if ( is_numeric( $i ) ) {
$out[$prefix . $i] = $v;
continue;
}
$out[$i] = $v;
}
return $out;
}
Additionally, upon reading XMLWriter usage, I believe you would be writing XML in a bad way.
<section>
<foo_0></foo_0>
<foo_1></foo_1>
<bar></bar>
<foo_2></foo_2>
</section>
Is not good XML.
<section>
<foo></foo>
<foo></foo>
<bar></bar>
<foo></foo>
</section>
Is better XML, because when intrepreted, the names being duplicate don't matter because they're all offset numerically like so:
section => {
0 => [ foo , {} ]
1 => [ foo , {} ]
2 => [ bar , {} ]
3 => [ foo , {} ]
}
This is an example prefixing all the keys with an underscore.
We use array_combine to combine the array keys with the array values, but we first run an array_map function on the array keys, which takes a simple function that adds the prefix.
$prefix = '_';
$arr = array_combine(
array_map(function($v) use ($prefix){
return $prefix.$v;
}, array_keys($arr)),
array_values($arr)
);
See a live example here https://3v4l.org/HABl7
I added this for an answer to another question and seemed relevant. Hopefully might help someone that needs to change the value of the keys in an array. Uses built-in functions for php.
$inputArray = array('app_test' => 'test', 'app_two' => 'two');
/**
* Used to remap keys of an array by removing the prefix passed in
*
* Example:
* $inputArray = array('app_test' => 'test', 'app_two' => 'two');
* $keys = array_keys($inputArray);
* array_walk($keys, 'removePrefix', 'app_');
* $remappedArray = array_combine($keys, $inputArray);
*
* #param $value - key value to replace, should be from array_keys
* #param $omit - unused, needed for prefix call
* #param $prefix - prefix to string replace in keys
*/
function removePrefix(&$value, $omit, $prefix) {
$value = str_replace($prefix, '', $value);
}
// first get all the keys to remap
$keys = array_keys($inputArray);
// perform internal iteration with prefix passed into walk function for dynamic replace of key
array_walk($keys, 'removePrefix', 'app_');
// combine the rewritten keys and overwrite the originals
$remappedArray = array_combine($keys, $inputArray);
// see full output of comparison
var_dump($inputArray);
var_dump($remappedArray);
Output:
array(2) {
'attr_test' =>
string(4) "test"
'attr_two' =>
string(3) "two"
}
array(2) {
'test' =>
string(4) "test"
'two' =>
string(3) "two"
}
I think that he want:
$a = array(1=>'first_name', 2=>'last_name');
$a = array_flip($a);
$a['first_name'] = 3;
$a = array_flip($a);
print_r($a);
The solution to when you're using XMLWriter (native to PHP 5.2.x<) is using $xml->startElement('itemName'); this will replace the arrays key.
change array key name "group" to "children".
<?php
echo json_encode($data);
function array_change_key_name( $orig, $new, &$array ) {
foreach ( $array as $k => $v ) {
$res[ $k === $orig ? $new : $k ] = ( (is_array($v)||is_object($v)) ? array_change_key_name( $orig, $new, $v ) : $v );
}
return $res;
}
echo '<br>=====change "group" to "children"=====<br>';
$new = array_change_key_name("group" ,"children" , $data);
echo json_encode($new);
?>
result:
{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","group":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","group":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","group":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}
=====change "group" to "children"=====
{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","children":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","children":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","children":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}
Use array array_flip in php
$array = array ( [1] => Sell [2] => Buy [3] => Rent [4] => Jobs )
print_r(array_flip($array));
Array ( [Sell] => 1 [Buy] => 2 [Rent] => 3 [Jobs] => 4 )
I did this for an array of objects. Its basically creating new keys in the same array and unsetting the old keys.
public function transform($key, $results)
{
foreach($results as $k=>$result)
{
if( property_exists($result, $key) )
{
$results[$result->$key] = $result;
unset($results[$k]);
}
}
return $results;
}
<?php
$array[$new_key] = $array[$old_key];
unset($array[$old_key]);
?>
To have the same key I think they must be in separate nested arrays.
for ($i = 0; $i < count($array); $i++) {
$newArray[] = ['name' => $array[$i]];
};
Output:
0 => array:1 ["name" => "blabla"]
1 => array:1 ["name" => "blabla"]
2 => array:1 ["name" => "blblll"]
You could create a new array containing that array, so:
<?php
$array = array();
$array['name'] = $oldArray;
?>

Categories