php: Adding one array as a new level in a multidimensional array - php

Assuming I have two arrays:
$a = ['a', 'b' => array('Jack', 'John'), 'c'];
$b = ['1', '2', '3'];
How can I push $b to be "under" the value 'Jack' in $a, to make it a multidimensional array? So, the end result should look like this:
$ab = ['a', 'b' => ['Jack' => ['1', '2', '3'], 'John'], 'c'];
I understand that this changes the value of $a[1]['Jack'] = 'b' to become a key, but that's fine with me.
How can I do this?

You can recursively iterate through the array with a function until you get the right value ('Jack') like this:
function iterateArr (&$array) {
if (is_array($array)) {
foreach ($array as $key => &$val) {
if (is_array($val)) {
iterateArr($val);
} elseif ($val == 'Jack') {
global $b;
unset($array[$key]);
$array[$val] = $b;
}
}
}
}
iterateArr($a);
For your example, this'd output:
['a', 'b' => ['John', 'Jack' => ['1', '2', '3']], 'c']
eval.in demo
But the beauty of this is that it'll work no matter how many levels deep your array is, since it's a recursive iterator. e.g., for an array like:
['a', 'b' => ['1', '2', '3' => ['i' => ['Jack', 'John'], 'ii', 'ii', 'iv', 'v']], 'c']
The output'd be:
['a', 'b' => ['1', '2', '3' => ['i' => ['John', 'Jack' => ['1', '2', '3']], 'ii', 'ii', 'iv', 'v']], 'c']
eval.in demo

$a = ['a', 'b' => array('Jack', 'John'), 'c'];
$b = ['1', '2', '3'];
unset($a['b'][0]); // go inside array $a and get the first value (B in
// this case)
// Then get the key you wanna change.
// Remove that value so we can 'reset' it.
$a['b'][0] = $b; // set array $b as that value;

Related

PHP append a sub-array into another array [duplicate]

I have two arrays like this:
array(
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44'
);
array(
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);
I want to combine these two array such that it does not contains duplicate and as well as keep their original keys. For example output should be:
array(
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);
I have tried this but it is changing their original keys:
$output = array_unique( array_merge( $array1 , $array2 ) );
Any solution?
Just use:
$output = array_merge($array1, $array2);
That should solve it. Because you use string keys if one key occurs more than one time (like '44' in your example) one key will overwrite preceding ones with the same name. Because in your case they both have the same value anyway it doesn't matter and it will also remove duplicates.
Update: I just realised, that PHP treats the numeric string-keys as numbers (integers) and so will behave like this, what means, that it renumbers the keys too...
A workaround is to recreate the keys.
$output = array_combine($output, $output);
Update 2: I always forget, that there is also an operator (in bold, because this is really what you are looking for! :D)
$output = $array1 + $array2;
All of this can be seen in:
http://php.net/manual/en/function.array-merge.php
You should take to consideration that $array1 + $array2 != $array2 + $array1
$array1 = array(
'11' => 'x1',
'22' => 'x1'
);
$array2 = array(
'22' => 'x2',
'33' => 'x2'
);
with $array1 + $array2
$array1 + $array2 = array(
'11' => 'x1',
'22' => 'x1',
'33' => 'x2'
);
and with $array2 + $array1
$array2 + $array1 = array(
'11' => 'x1',
'22' => 'x2',
'33' => 'x2'
);
This works:
$output = $array1 + $array2;
The new way of doing it with php7.4 is Spread operator [...]
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
var_dump($fruits);
Spread operator should have better performance than array_merge
A significant advantage of Spread operator is that it supports any traversable objects, while the array_merge function only supports arrays.
To do this, you can loop through one and append to the other:
<?php
$test1 = array(
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44'
);
$test2 = array(
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);
function combineWithKeys($array1, $array2)
{
foreach($array1 as $key=>$value) $array2[$key] = $value;
asort($array2);
return $array2;
}
print_r(combineWithKeys($test1, $test2));
?>
UPDATE: KingCrunch came up with the best solution: print_r($array1+$array2);
If you are using PHP 7.4 or above, you can use the spread operator ... as the following examples from the PHP Docs:
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3]
function getArr() {
return ['a', 'b'];
}
$arr6 = [...getArr(), 'c']; //['a', 'b', 'c']
$arr7 = [...new ArrayIterator(['a', 'b', 'c'])]; //['a', 'b', 'c']
function arrGen() {
for($i = 11; $i < 15; $i++) {
yield $i;
}
}
$arr8 = [...arrGen()]; //[11, 12, 13, 14]
It works like in JavaScript ES6.
See more on https://wiki.php.net/rfc/spread_operator_for_array.
This works:
$a = array(1 => 1, 2 => 2, 3 => 3);
$b = array(4 => 4, 5 => 5, 6 => 6);
$c = $a + $b;
print_r($c);
Warning! $array1 + $array2 overwrites keys, so my solution (for multidimensional arrays) is to use array_unique()
array_unique(array_merge($a, $b), SORT_REGULAR);
Notice:
5.2.10+ Changed the default value of sort_flags back to SORT_STRING.
5.2.9 Default is SORT_REGULAR.
5.2.8- Default is SORT_STRING
It perfectly works. Hope it helps same.
https://www.php.net/manual/en/function.array-merge.php
<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
This is slightly explored by #jchook in one of his comments, but it is worth highlighting that the + is not as consistant as one might expect. When you are dealing with keys which are the same, the results are not the same as array_merge.
$a1 = array(
'hello',
'world',
);
$a2 = array(
'foo',
'baz',
);
// Will NOT work - only outputs $a1
print'<pre>';print_r($a1 + $a2);print'</pre>';
$a1 = array(
'a' => 'hello',
'b' => 'world',
);
$a2 = array(
'c' => 'foo',
'd' => 'baz',
);
// Will work (however were a and b c and d - would equally fail
print'<pre>';print_r($a1 + $a2);print'</pre>';
$a1 = array(
1=> 'hello',
2=> 'world',
);
$a2 = array(
3=>'foo',
4=>'baz',
);
// Will work
print'<pre>';print_r($a1 + $a2);print'</pre>';
We can combine two arrays in PHP using the spread operator (...).
In this example, $array1 contains the values 1 through 10, and $array2 contains the values 11 through 20.
The spread operator is used to concatenate(combine) the two arrays into a single array called $data.
// Define the first array
$array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Define the second array
$array2 = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
// Use the spread operator to concatenate the two arrays into a single array
$data = [...$array1, ...$array2];
// Print the contents of the combined array
print_r($data);

Merge column values from two arrays to form an indexed array of associative arrays

I have two arrays:
$a = ['0' => 1, '1' => 2, '2' => 3]
$b = ['0' => 4, '1' => 5, '2' => 6]
I want to create a new array like this:
[
['a' => 1, 'b' => '4'],
['a' => '2', 'b' => '5']
]
I have tried using array_merge and array_merge_recursive, but I wasn't able to get the right results.
$data = array_merge_recursive(array_values($urls), array_values($id));
You have to apply array_map() with custom function:
$newArray = array_map('combine',array_map(null, $a, $b));
function combine($n){
return array_combine(array('a','b'),$n);
}
print_r($newArray);
Output:-https://3v4l.org/okML7
Try this one
$c = array_merge($a,$b)
$d[] = array_reduce($d, 'array_merge', []);
It will merge the two array and reduce and remerge it.
You can use foreach to approach this
$a = ['0' => 1, '1' => 2, '2' => 3];
$b = ['0' => 4, '1' => 5, '2' => 6];
$res = [];
$i = 0;
$total = 2;
foreach($a as $k => $v){
$res[$i]['a'] = $v;
$res[$i]['b'] = $b[$k];
$i++;
if($i == $total) break;
}
The idea is to have an array $ab = ['a','b'] and a array from your both arrays like this $merged_array = [[1,4],[2,5],[3,6]]. Now we can combine array $ab with each element of $merged_array and that will be the result we need.
$first = ['0' => 1, '1' => 2, '2' => 3];
$second = ['0' => 4, '1' => 5, '2' => 6];
$merged_array = [];
for($i=0;$i<count($first);$i++)
{
array_push($merged_array,[$first[$i],$second[$i]]);
}
$final = [];
$ab = ['a','b'];
foreach($merged_array as $arr)
{
array_push($final,array_combine($ab, $arr));
}
print_r($final);
All earlier answers are working too hard. I see excessive iterations, iterated function calls, and counter variables.
Because there are only two arrays and the keys between the two arrays are identical, a simple foreach loop will suffice. Just push associative arrays into the result array.
Code: (Demo)
$a = ['0' => 1, '1' => 2, '2' => 3];
$b = ['0' => 4, '1' => 5, '2' => 6];
$result = [];
foreach ($a as $k => $v) {
$result[] = ['a' => $v, 'b' => $b[$k]];
}
var_export($result);
Output:
array (
0 =>
array (
'a' => 1,
'b' => 4,
),
1 =>
array (
'a' => 2,
'b' => 5,
),
2 =>
array (
'a' => 3,
'b' => 6,
),
)

How to replace key in multidimensional array and maintain order

Given this array:
$list = array(
'one' => array(
'A' => 1,
'B' => 100,
'C' => 1234,
),
'two' => array(
'A' => 1,
'B' => 100,
'C' => 1234,
'three' => array(
'A' => 1,
'B' => 100,
'C' => 1234,
),
'four' => array(
'A' => 1,
'B' => 100,
'C' => 1234,
),
),
'five' => array(
'A' => 1,
'B' => 100,
'C' => 1234,
),
);
I need a function(replaceKey($array, $oldKey, $newKey)) to replace any key 'one', 'two', 'three', 'four' or 'five' with a new key independently of the depth of that key. I need the function to return a new array, with the same order and structure.
I already tried working with answers from this questions but I can't find a way to keep the order and access the second level in the array:
Changing keys using array_map on multidimensional arrays using PHP
Change array key without changing order
PHP rename array keys in multidimensional array
This is my attempt that doesn't work:
function replaceKey($array, $newKey, $oldKey){
foreach ($array as $key => $value){
if (is_array($value))
$array[$key] = replaceKey($value,$newKey,$oldKey);
else {
$array[$oldKey] = $array[$newKey];
}
}
return $array;
}
Regards
This function should replace all instances of $oldKey with $newKey.
function replaceKey($subject, $newKey, $oldKey) {
// if the value is not an array, then you have reached the deepest
// point of the branch, so return the value
if (!is_array($subject)) return $subject;
$newArray = array(); // empty array to hold copy of subject
foreach ($subject as $key => $value) {
// replace the key with the new key only if it is the old key
$key = ($key === $oldKey) ? $newKey : $key;
// add the value with the recursive call
$newArray[$key] = replaceKey($value, $newKey, $oldKey);
}
return $newArray;
}

How do I combine two values from the same associative array?

I have an array that I need to get a value from within the same array that is unassigned to a variable:
return ['a' => 1, 'b'=> 'a', 'c' => 2];
So in this case I need 'b' to return the same value as 'a'. Which would be 1
Thanks for the help.
edit
I intend on running a function on b's value so the value of b is slightly different than a
return ['a' => 1, 'b'=> myFunction('a'), 'c' => 2];
You can try this way.
foreach ($array as $key => $agent) {
$array[$key]['agent_address_1'] = $agent['agent_company_1'] . ', ' .$agent['agent_address_1'];
unset($array[$key]['agent_company_1']);
}
What you want is not clear.
But i am assuming that you are trying to get the 'b' element of an array to be assigned a value similar to the value of 'a' element of that same array
If that is what you need, this will do it.
<?php
$a = array('a' => 1, 'b' => null, 'c' => 2);
$a['b'] = myFunction($a, 'a');
function myFunction($a, $b)
{
return $a[$b];
}
var_dump($a);
You can then return the array, or do what you want with it.
Maybe something like
<?php
function resolve(array $arr) {
foreach($arr as &$v) {
if ( isset($arr[$v])) {
$v = $arr[$v];
}
}
return $arr;
}
function foo() {
return resolve( ['a' => '5', 'b'=>'a', 'c' => '1'] );
}
var_export( foo() );
will do, prints
array (
'a' => '5',
'b' => '5',
'c' => '1',
)
But keep in mind that resolve( ['b'=>'a', 'a' => 'c', 'c' => '1'] ); will return
array (
'b' => 'c',
'a' => '1',
'c' => '1',
)
(you could resolve that with while( isset($arr[$v])) { instead of if ( isset($arr[$v]) ) { ...but there are most likely more elegant/performant ways to do that)

Reverse array values while keeping keys

Here is an array I have:
$a = array('a' => 'a1', 'b' => 'a2', 'c' => 'a3', 'd' => 'a4', 'e' => 'a5');
What I would like to do is reverse the values of the array while keeping the keys intact, in other words it should look like this:
$a = array('a' => 'a5', 'b' => 'a4', 'c' => 'a3', 'd' => 'a2', 'e' => 'a1');
How should I go about it?
P.S. I tried using array_reverse() but it didn't seem to work
Some step-by-step processing using native PHP functions (this can be compressed with less variables):
$a = array('a' => 'a1', 'b' => 'a2', 'c' => 'a3', 'd' => 'a4', 'e' => 'a5');
$k = array_keys($a);
$v = array_values($a);
$rv = array_reverse($v);
$b = array_combine($k, $rv);
var_dump($b);
Result:
array(5) {
'a' =>
string(2) "a5"
'b' =>
string(2) "a4"
'c' =>
string(2) "a3"
'd' =>
string(2) "a2"
'e' =>
string(2) "a1"
}
It is possible by using array_combine, array_values, array_keys and array_values. May seem like an awful lot of functions for a simple task, and there may be easier ways though.
array_combine( array_keys( $a ), array_reverse( array_values( $a ) ) );
Here another way;
$keys = array_keys($a);
$vals = array_reverse(array_values($a));
foreach ($vals as $k => $v) $a[$keys[$k]] = $v;
I think this should work..
<?php
$old = array('a' => 'a1', 'b' => 'a2', 'c' => 'a3', 'd' => 'a4', 'e' => 'a5');
$rev = array_reverse($old);
foreach ($old as $key => $value) {
$new[$key] = current($rev);
next($rev);
}
print_r($new);
?>
This'll do it (just wrote it, demo here):
<?php
function value_reverse($array)
{
$keys = array_keys($array);
$reversed_values = array_reverse(array_values($array), true);
return array_combine($keys, $reversed_values);
}
$a = array('a' => 'a1', 'b' => 'a2', 'c' => 'a3', 'd' => 'a4', 'e' => 'a5');
print_r( value_reverse($a) );

Categories