PHP array_merge key order - php

Does it matter in what order the keys in an array array doing an array_merge, i.e. would the keys in the second array below override the keys in the first array:
array1 = array('username' => 'abc', 'level' => 'admin', 'status' => 'active');
array2 = array('level' => 'root', 'status' => 'active', 'username' => 'bcd');
? Or would the order of the keys have to be the same in the two arrays?

The manual states the answer to this question:
Merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns
the resulting array.
If the input arrays have the same string keys, then the later value
for that key will overwrite the previous one. If, however, the arrays
contain numeric keys, the later value will not overwrite the original
value, but will be appended.
So, yes the keys in the second array will overwrite the keys from the first one if the second array contains some of the same keys.
$array1 = array('username' => 'abc', 'level' => 'admin', 'status' => 'active');
$array2 = array('level' => 'root', 'status' => 'active', 'username' => 'bcd');
$new = array_merge($array1, $array2);
print_r($new);
Output:
Array
(
[username] => bcd
[level] => root
[status] => active
)
So you can see that the keys from the second array overwrote the same keys from first one; the order of the keys in each array does not matter.

Here is an alternative solution that allows the use of a template array to define the output order. Missing fields are filled with null or as specified. In this example the first and last fields are filled with ---.
Please take note of the highlighted text from the previous answer about numeric keys.
function array_merge_template($array1, $array2, $template, $fill=null) {
$_template = array_fill_keys($template, $fill);
return array_intersect_key ( array_replace ( $_template, array_merge($array1, $array2)) , $_template);
}
Input:
$array1 = ['username' =>'abc', 'level' =>'admin', 'status' =>'active', 'foo'=>'x'];
$array2 = ['level' =>'root', 'status' =>'active', 'username' =>'bcd', 'bar'=>'y'];
$template = ['first','level','foo','username','bar','status','last'];
Output:
/* array_merge($array1,$array2) */
[
"username" => "bcd",
"level" => "root",
"status" => "active",
"foo" => "x",
"bar" => "y"
]
/* array_merge_template($array1,$array2,$template,'---') */
[
"first" => "---",
"level" => "root",
"foo" => "x",
"username" => "bcd",
"bar" => "y",
"status" => "active",
"last" => "---"
]

Related

How can i do merge arrays by my specific situation

I have to arrays, these:
$array1 = [
'red' => 'pencil',
'blue' => 'eraser',
];
$array2 = [
'reding' => '',
'bluing' => '',
];
and i wanna get this output:
$output = [
'reding' => 'pencil',
'bluing' => 'eraser',
];
So, values come from $array1 and keys come from $array2 on the $output.
Note: elements in array count is variable.
How can i do this ? Thanks for your helps.
if arrays are always the same length
array_combine(array_keys($array2), $array1);
array array_combine ( array $keys , array $values )
Creates an array by using the values from the keys array as keys and the values from the values array as the corresponding values.
More Details here

PHP Merge two arrays in to each other, using an index array as a reference - Two arrays as output

I am trying to take two arrays, and merge them to each other. The first array serves as an 'index' array, that is - that is the format that the output arrays desirably would be:
$array1 = [
'DIV1' => 'Some element data',
'SUPPLEMENTAL' => [
'RPC' => '10.24.122.32',
'PORT' => '8080'
],
'ASG' => 'some arbitrary data'
];
$array2 = [
'DIV2' => 'Some more element data',
'ASG' => 'different arbitrary data',
'DIV1' => 'Some element data that refers to the other object'
'SUPPLEMENTAL' => [
'RPC' => '10.24.123.1'
]
];
So after the merge, we would effectively have two arrays. This can be done as a a single function called twice, which passes each array as parameters (reversed for the second call - and somehow defining the index array). The keys would be carried over -only-, no values. We would end up with arrays looking like this:
$array1 = [
'DIV1' => 'Some element data',
'DIV2' => '', // blank because only key was moved
'SUPPLEMENTAL' => [
'RPC' => '10.24.122.32',
'PORT' => '8080'
],
'ASG' => 'some arbitrary data'
];
$array2 = [
'DIV1' => 'Some element data that refers to the other object'
'DIV2' => 'Some more element data',
'SUPPLEMENTAL' => [
'RPC' => '10.24.123.1',
'PORT' => '' // blank because only key was moved
],
'ASG' => 'different arbitrary data'
];
It is not -extremely- important that the imported (blank) keys are put in some order, but the preservation of order of existing elements is important. As long as it abides by the index arrays order definition (array1 in this case).
I think I would need to do some sort of nested sort for the multiple dimensions.
Because your data doesn't have keys in the same order it'll be difficult to maintain key order, but you can achieve what you need with a recursive function:
function recursiveReKeyArrays(array $array1, array $array2)
{
// Loop through the array for recursion
foreach ($array2 as $key => $value) {
if (!is_array($value)) {
continue;
}
$array1[$key] = recursiveReKeyArrays($array1[$key], $value);
}
// Find the differences in the keys
foreach (array_diff_key($array2, $array1) as $key => $value) {
$array1[$key] = null;
}
return $array1;
}
This will loop through the second array, find any values which are arrays and recurse into them and find any missing keys and set them to null.
This will give you this output:
Array
(
[DIV1] => Some element data
[SUPPLEMENTAL] => Array
(
[RPC] => 10.24.122.32
[PORT] => 8080
)
[ASG] => some arbitrary data
[DIV2] =>
)
Array
(
[DIV2] => Some more element data
[ASG] => different arbitrary data
[DIV1] => Some element data that refers to the other object
[SUPPLEMENTAL] => Array
(
[RPC] => 10.24.123.1
[PORT] =>
)
)
Example here: http://ideone.com/5ml1y4

Laravel/PHP renaming associative keys without knowing their names

Given following collection/array:
[
"somename" => "test.test.be"
"anothername" => "test"
"yetanothername" => "testing"
"extrafield" => "extra",
"extrafield" => "extra",
]
When i retrieve this collection i always know the order of them, but i will not know the key-names. So what i want to do is transform this collection and change the keynames to my defined values.
For a non-associative array i would do something like
$trimmedCollection->transform(function ($item) {
return [
'email' => $item[0],
'first_name' => $item[1],
'surname' => $item[2],
];
});
But how would i handle this for the given collection? Also what to do with overflow items. Say i suddenly got 10 key-value pairs but only wrote a transform for 3 how would i transform all the overflow to a default key?
Edit:
For the overflow items i would like to assign all extra fields in the given array to be stored like so.
Below would be the final array:
[
"email" => "test.test.be"
"first_name" => "test"
"surname" => "testing"
"additional_fields" => ["key-name" => "extra","key-name" => "extra"]
]
Where the key-name is the original name of the key i retrieved.
You can use array_shift to remove the 1st element in the array for every known element, and add the remaining array to your additional_fields key:
$trimmedCollection->transform(function ($item) {
return [
'email' => array_shift($item), //$item[0]
'first_name' => array_shift($item), //$item[1]
'surname' => array_shift($item), //$item[2]
'additional_fields' => $item //all remaining items
];
});
You could do something like this to transform your selected keys. This retains the other values with their unchanged keys.
function replace_array_key(array &$item, $oldKey, $newKey)
{
$item[$newKey] = $item[$oldKey];
unset($item[$oldKey]);
}
$trimmedCollection->transform(function ($item) {
replace_array_key($item, 'somename', 'email');
replace_array_key($item, 'anothername', 'first_name');
replace_array_key($item, 'yetanothername', 'surname');
return $item;
});
You can even extend this to an array list of old and new key names and run it through and arrap_map.

filter an array by key value that has pipes in it

I have a form that will need to except input from users to filter the search results. I am not the original designer of the form. I one of two ways that I saw to filter the results. A) I could have tried to restrict the sql query to the selected codes or B) filter the results that are returned. I am trying B.
I have tried
var_dump(array_intersect_key($array1, $array2));
No success:
Array1 looks like this:
array (
'|00006|5' => array('pid' => 111
'provider_id' => 123456 )
'|93000|34' => array('pid' => 112
'provider_id' => 127654 )
'|93225|1' => array('pid' => 113
'provider_id' => 127893 )
)
I figured out how the pipes got into the key values and I tried to adjust my keys to match but that did not work either.
Any suggestions on how I can filter these types of results with a key that is not a single value and is dynamically changed?
Array2 look like:
99232 => string '99232' (length=5)
85610 => string '85610' (length=5)
93970 => string '93970' (length=5)
93000 => string '93000' (length=5)
99406 => string '99406' (length=5)
99215 => string '99215' (length=5)
I made the key value and the string value the same trying to setup some type of filtering.
But since the third value in array1 will be dynamically delivered in a while clause. I have no way of matching that number to the Array2.
My expected outcome is
array (
'|93000|34' => array('pid' => 112
'provider_id' => 127654 )
)
As that only one of the 6 inputs matched one of the array1 values.
You have to define your key comparison function and then use array_intersect_ukey():
$a = array (
'|00006|5' => array('pid' => 111,
'provider_id' => 123456 ),
'|93000|34' => array('pid' => 112,
'provider_id' => 127654 ),
'|93225|1' => array('pid' => 113,
'provider_id' => 127893 ),
);
$b = array('93000' => '93000');
print_r(array_intersect_ukey($a, $b, function($ka, $kb) {
if ($ka[0] == '|') { // transform key
$ka = substr($ka, 1, strrpos($ka, '|') - 1);
}
if ($kb[0] == '|') { // transform key
$kb = substr($kb, 1, strrpos($kb, '|') - 1);
}
// perform regular comparison
return strcmp($ka, $kb);
}));
or you can do this.
good luck :)
$parsed1 = array();
foreach($array1 as $key => $value) {
$splited = explode("|", $key);
$parsed1[$splited[1]] = $value;
}
var_dump(array_intersect_key($parsed1,$array2));

Merging multiple multidimensional arrays

I have a variable number of multidimensional arrays but all with the same 4 possible values for each item.
For example:
Array
(
[companyid] => 1
[employeeid] => 1
[role] => "Something"
[name] => "Something"
)
but every array may have a different ammount of items inside it.
I want to turn all the arrays into one single table with lots of rows. I tried array_merge() but I end up with a table with 8, 12, 16... columns instead of more rows.
So... any ideas?
Thanks
Didn't test it, but you could try the following:
$table = array();
$columns = array('companyid' => '', 'employeeid' => '', 'role' => '', 'name' => '');
foreach($array as $item) {
$table[] = array_merge($columns, $item);
}
This should work since the documentation about array_merge say:
If the input arrays have the same string keys, then the later value
for that key will overwrite the previous one.
So you either get the value of the current item or a default value that you can specify in the $columns array.
$array1=Array
(
"companyid" => 1,
"employeeid" => 4,
"role" => "Something",
"name" => "Something",
);
$array2=Array
(
"companyid" => array(2,2,2),
"employeeid" => 5,
"role" => "Something2",
"name" => "Something2"
);
$array3=Array
(
"companyid" => 3,
"employeeid" => 6,
"role" => "Something3",
"name" => "Something3"
);
//Using array_merge
$main_array["companyid"]=array_merge((array)$array1["companyid"],(array)$array2["companyid"],(array)$array3["companyid"]);
$main_array["employeeid"]=array_merge((array)$array1["employeeid"],(array)$array2["employeeid"],(array)$array3["employeeid"]);
for($i=0;$i<count($main_array["companyid"]);$i++)
echo $main_array["companyid"][$i] + "<br />";
for($i=0;$i<count($main_array["employeeid"]);$i++)
echo $main_array["employeeid"][$i] + "<br />";
I've tested the code above and seems right.
You coult also improve this code into a DRY function.

Categories