PHP - merging arrays - php

I have two arrays...
$arr1 = array(
'name',
'date' => array('default' => '2009-06-13', 'format' => 'short'),
'address',
'zipcode' => array('default' => 12345, 'hidden' => true)
);
$arr2 = array(
'name',
'language',
'date' => array('format' => 'long', 'hidden' => true),
'zipcode' => array('hidden' => false)
);
Here's the desired result:
$final = array(
'name',
'date' => array('default' => '2009-06-13', 'format' => 'long', 'hidden' => true),
'zipcode' => array('default' => 12345, 'hidden' => false)
);
Only the elements from $arr2 (that also exist in $arr1) are used
Each element's attributes are merged
If a common element (e.g. zipcode) shares an attribute (e.g. hidden), then the attribute from $arr2 takes precedence
What are some good approaches for solving this problem?
Thanks in advance.
EDIT: I tried to hobble something together... critiques welcomed:
$new_array = array_intersect_key($arr2, $arr1);
foreach ($new_array as $key => $val)
{
if (is_array($arr1[$key]))
{
if (is_array($val))
{
$new_array[$key] = array_merge($val, $arr1[$key]);
}
else
{
$new_array[$key] = $arr1[$key];
}
}
}

You were close
$newArr = array_intersect_key($arr1, $arr2);
foreach ($newArr as $key => $val)
{
if (is_array($val))
{
$newArr[$key] = array_merge($arr1[$key], $arr2[$key]);
}
}
Edit
Just had to change the array_intersect to array_intersect_key

you might find array_intersect() useful
link text

Related

Convert all values into a single string in a multi-dimension PHP array?

$array = array(
array(
'id' => 1,
'first_name' => 'testOne',
),
array(
'id' => 333,
'first_name' => 'test333',
)
);
Required Output:
array("1_testOne","333_test333");
This should help -
array_map(function($a) {
return implode('_', $a); // implode all with '_'
}, $array);
array_map()
$array = array(
array(
'id' => 1,
'first_name' => 'testOne',
),
array(
'id' => 333,
'first_name' => 'test333',
)
);
$new_array = [];
foreach($array as $key => $value) {
$new_array[] = $value['id'] . "_" . $value['first_name'];
}
echo "<pre>";
print_r($new_array);
It will return output as
Array('1_testOne', '333_test333')

Create multidimensional array recursively

The original array looks like this:
$array = array(
array(
'key' => 'key1',
'val' => 'val1'
),
array(
'key' => 'key2:subkey1',
'val' => 'val2'
),
array(
'key' => 'key3:subkey2',
'val' => 'val3'
),
array(
'key' => 'key3:subkey3:subsubkey1',
'val' => 'val4'
),
array(
'key' => 'key3:subkey3:subsubkey2',
'val' => 'val5'
),
array(
'key' => 'key3:subkey3:subsubkey3',
'val' => 'val6'
)
);
And I want to generate a new array based on the original one that looks like this:
$result = array(
'key1' => 'val1',
'key2' => array(
'subkey1' => 'val2'
),
'key3' => array(
'subkey2' => 'val3',
'subkey3' => array(
'subsubkey1' => 'val4',
'subsubkey2' => 'val5',
'subsubkey3' => 'val6'
)
)
);
The algorithm should be able to handle a reference array of any depth.
What I have tried so far works, but I am not happy with using eval for various reasons:
function convert($array) {
$out = array();
foreach ($array as $data) {
$key = $data['key'];
$pos = strpos($key, ':');
if ($pos === false) {
$out[$key] = $data['val'];
} else {
$split = explode(":", $key);
eval("\$out['" . implode("']['", $split) . "'] = '" . $data['val'] . "';");
}
}
return $out;
}
Is there a way to solve this without resorting to eval, i.e. setting the $out directly? The val comes from user input, so it is obviously very unsafe to use eval in this case.
Thank you for your advice.
function convert($array) {
$out = array();
foreach ($array as $data) {
$key = $data['key'];
$value = $data['val'];
$helper = &$out;
foreach (explode(':', $key) as $i) {
$helper = &$helper[$i];
}
$helper = $value;
}
return $out;
}
Took me a while to figure out how to do it. References are perhaps the best way to achieve it.
The $helper-variable is a temporary reference to the $out-array we want to return after we're done. It splits each key by the colon as delimiter and iterates through each individual key. In every iteration we change the helper reference to the next key.
An example:
$out = array();
explode(':', $key) => array('key3', 'subkey3', 'subsubkey1');
$helper = &$out;
// foreach loop starts
$helper = $helper['key3']; // Iteration 1
$helper = $helper['key3']['subkey3']; // Iteration 2
$helper = $helper['key3']['subkey3']['subsubkey1']; // Iteration 3
I hope you understand how it works.
Try this neat code:
$array = array(
array(
'key' => 'key1',
'val' => 'val1'
),
array(
'key' => 'key2:subkey1',
'val' => 'val2'
),
array(
'key' => 'key3:subkey2',
'val' => 'val3'
),
array(
'key' => 'key3:subkey3:subsubkey1',
'val' => 'val4'
),
array(
'key' => 'key3:subkey3:subsubkey2',
'val' => 'val5'
),
array(
'key' => 'key3:subkey3:subsubkey3',
'val' => 'val6'
)
);
$new_array = array();
foreach($array as $element) {
$temp = &$new_array;
foreach(explode(':', $element['key']) as $key) {
$temp = &$temp[$key];
}
$temp = $element['val'];
}
unset($temp);
var_dump($new_array);

Recursive get path from multidimensional php array

I have array:
$adm_menu_old = array (
array(
'id' => 1,
'name' => 'Test1',
),
array(
'id' => 3,
'name' => 'Test3',
'childrens' => array(
array(
'id' => 31,
'name' => 'Test31',
),
array(
'id' => 32,
'name' => 'Test32',
'childrens' => array(
array(
'id' => 321,
'name' => 'Test321',
),
),
)
),
array(
'id' => 4,
'name' => 'Test4',
),
);
Say i know id value.
I need get path with all parents of this id.
For example i need get path to this element: id=321
i need get array with key name values:
array('Test3','Test32','Test321')
how should look like recursive function?
Try this function:
function getNames($id, $arr) {
$result = array();
foreach($arr as $key => $val) {
if(is_array($val)) {
if($val["id"] == $id) {
$result[] = $val["name"];
} elseif(!empty($val["childrens"]) && is_array($val["childrens"])) {
$sub_res = getNames($id, $val["childrens"]);
if(count($sub_res) > 0) {
$result[] = $val["name"];
$result = array_merge($result, $sub_res);
}
}
}
}
return $result;
}

How to change the index name of array

I have a multidimensional array,
I'm recursively changing values of array with I need.
It is working for keys which are not array.
But not for keys which are array.
How can I change value of one to test like "one" => "test",
$arr = array(
'one' => array(
array('something' => 'value'),
array('something2' => 'value2'),
'another' => 'anothervalue'
),
'two' => array(
array('something' => 'value'),
array('something2' => 'value2'),
'another' => 'anothervalue'
)
);
function update_something(&$item, $key)
{
if($key == 'one')
$item = 'test';
}
array_walk_recursive($arr, 'update_something');
EXPECTED ARRAY STRUCTURE IS
array(
'one' => 'test',
'two' => array(
array('something' => 'value'),
array('something2' => 'value2'),
'another' => 'anothervalue'
)
);
UPDATE2
$html_structure = array(
array(
'tag' => 'div',
'class' => 'lines',
array(
'tag' => 'div',
'one' => array(
'tag' => 'div',
array(
'tag' => 'span',
'style' => 'margin:10px; padding:10px',
'key' => 'title',
),
'key' => 'subject',
)
)
)
);
UPDATE3
$array = array(
array(
'tag' => 'div',
'class' => 'lines',
array(
'tag' => 'div',
'repeat' => array(
'tag' => 'div',
array(
'tag' => 'span',
'style' => 'margin:10px; padding:10px',
'key' => 'title',
),
'key' => 'subject',
)
)
)
);
function update_recursively($array, $key = '', $value = array()) {
//print_r($array); print_r($value);
foreach ($array as $k => $v) {
if ($k === $key){
$array[$k] = $value;
}
elseif (is_array($v))
$array[$k] = update_recursively($v);
}
return $array;
}
print_r(update_recursively($array, 'repeat', array('d' => 'a')));
If you array isn't too large, something like this would work:
function update_recursively($array) {
foreach ($array as $k => $v) {
if ($k === 'one')
$array[$k] = 'test';
elseif (is_array($v))
$array[$k] = update_recursively($v);
}
return $array;
}
$updated_arr = update_recurisvely($arr);
But you need to be a bit careful if it's really big as it can get slow and memory intensive. Note that it won't update your old array, like array_walk_recursive would, it will return an updated version instead.
* UPDATE *
Version that handles the Update3 scenario where we specify key to look for and value to replace it with.
function update_recursively($array, $key = '', $value = array()) {
foreach ($array as $k => $v) {
if ($k === $key)
$array[$k] = $value;
elseif (is_array($v))
$array[$k] = update_recursively($v, $key, $value);
}
return $array;
}
You can try:
function update_something(&$item, $key) {
if($key == 'one') {
array_splice($item,0,'test');
}
}

PHP: how to return multi dimension array from recursive function

This is my code,
and I need your help to understand it.
<?php $tree = array(
array(
'name' => 'Item-1',
'children' => array()),
array('name' => 'Item-2',
'children' => array(
array('name' => 'Item-2-1',
'children' => array()),
)),
array('name' => 'Item-3',
'children' => array(
array('name' => 'Item-3-1',
'children' => array()),
array('name' => 'Item-3-2',
'children' => array(
array('name' => 'Item-3-2-1',
'children' => array()),
array('name' => 'Item-3-2-2',
'children' => array()),
array('name' => 'Item-3-2-3',
'children' => array(
array('name' => 'Item-3-2-3-1',
'children' => array()),
)),
)),
)),
);
What i need is one recursive function, which will return all names (name).
For example:
Item-1
Item-2
Item-2-1
Item-3
Item-3-1
Item-3-2
........
My attempt but it just doesn't seem to work for me
function tree($tree){
foreach ($tree as $key =>$value) {
foreach ($value as $key=>$value){
echo "$value<br>"; }
echo "<br>"; } }
You can use RecursiveArrayIterator and RecursiveIteratorIterator
$ai = new RecursiveIteratorIterator(new RecursiveArrayIterator($tree));
echo "<pre>";
foreach ( $ai as $value ) {
echo $value, PHP_EOL;
}
Output
Item-1
Item-2
Item-2-1
Item-3
Item-3-1
Item-3-2
Item-3-2-1
Item-3-2-2
Item-3-2-3
Item-3-2-3-1
See Live Demo
From http://snipplr.com/view/10200/
// Recursively traverses a multi-dimensional array.
function traverseArray($array)
{
// Loops through each element. If element again is array, function is recalled. If not, result is echoed.
foreach($array as $key=>$value)
{
if(is_array($value))
{
traverseArray($value);
}else{
echo $key." = ".$value."<br />\n";
}
}
}
Also see Sum integers in 2d array using recursion?

Categories