PHP merging arrays without overwriting data - php

I have a number of arrays, and I wish to merge them without overwriting or losing any data. I believe they are called associative arrays but I am not 100% sure about the terminology .
The arrays contain information like this:
$array1['title']
$array1['description']
$array2['title']
$array2['description']
$array2['random information']
I want to merge the information contained within the common keys of $array1 and $array2 without overwriting any data.
Is this possible?
Things I have tried, that were not successful, include the following:
(array)$array3 = (array)$array1 + array($array2);
$array3 = array_push($array1,$array2);
$array3 = array_merge_recursive($array1,$array2);
Essentially I want to retain the common keys, and add the information from both arrays into the new array. For example, I only want one ['title'] ['description'] etc in the new array but I want the information from both arrays in the new array.
So $array3 will contain all the information that was in $array1 and $array2... all the items from ['title'] ['description'] will be retained under ['title'] ['description'] in $array3.
Is this possible?
Thanks guys.

I have found using array_replace_recursive nested works. This first call creates an array merged which may have some values removed, the second call will remerge back into your master array keeping all array keys from the master array but allowing the merged in array to overwrite values in the master.
$mergedArray = array_replace_recursive($array2, array_replace_recursive($array1, $array2));

I would merge all the keys, then merge the arrays, like so:
$merged = array();
foreach( array_merge( array_keys( $array1), array_keys( $array2)) as $key) {
$values = array();
if( array_key_exists( $key, $array1)) {
$values[] = $array1[$key];
}
if( array_key_exists( $key, $array2)) {
$values[] = $array2[$key];
}
$merged[$key] = $values;
}
You can see from this demo that this creates an array like:
Array
(
[title] => Array
(
[0] => title1
[1] => title2
)
[description] => Array
(
[0] => desc1
[1] => desc2
)
[random information] => Array
(
[0] => random2
)
)

Related

dynamically nested array map using php

I have an array of list keys like:
$list_map_key=[
['pn','pn1','pp','pp1'],
['pn','pn1','pp','pp2'],
['pn','pn2','pp','pp5'],
['pn','pn2'],
];
I want to build map key array like this to replace value of (pp)
$data_return['pn']['pn1']['pp']['pp1']=3000;
$data_return['pn']['pn1']['pp']['pp2']=3000;
$data_return['pn']['pn2']['pp']['pp5']=3000;
$data_return['pn']['pn2']=3000;
But the keys to the array $data_return['pn']['pn1']['pp']['pp1'] must be dynamically generated from the array key list.
I want to build some function to call position data from list array key and add, replace or delete data.
The exact output you want is not achievable since $data_return['pn']['pn2'] cannot simultaneously be an array and a value. However you can achieve something similar with this code. The function push_value takes an array of keys and pushes the value into a multi-dimensional array according to those keys. Then we generate $data_return by looping over each individual value in $list_map_key and using array_merge_recursive to merge the individual arrays together:
function push_value($keys, $value) {
$key = array_shift($keys);
if (count($keys)) {
return array($key => push_value($keys, $value));
}
else {
return array($key => $value);
}
}
$data_return = array();
$value = 3000;
foreach ($list_map_key as $keys) {
$data_return = array_merge_recursive($data_return, push_value($keys, $value));
}
print_r($data_return);
Output:
Array
(
[pn] => Array
(
[pn1] => Array
(
[pp] => Array
(
[pp1] => 3000
[pp2] => 3000
)
)
[pn2] => Array
(
[pp] => Array
(
[pp5] => 3000
)
[0] => 3000
)
)
)
Demo on 3v4l.org

Combine dynamic arrays with dynamic keys in to single arrays

I have this dynamic multiple arrays that I need to combine in one array and serialized them. The problem is I need to keep both key and value.
$arr = array($bet_option_id => $bet_option_name);
Here i need to keep both bet_option_id AND bet_option_name. Then this result output:
Array ( [997650802] => Over 2.5 )
Array ( [997650807] => Yes )
This need to be simply
Array
(
[997650802] => Over 2.5
[997650807] => Yes
)
As it's dynamic, sometimes not comes with just single array so apparently I couldn't get it working. I need to retrieve both bet_option_id & bet_option_name. Tried something like this:
$arr = array($bet_option_id => $bet_option_name); //This is where all array keys, values are stores
$result = array();
foreach ($arr as $array) {
$result = array_merge($result, $array);
}
Any inputs will be nice.
Rather than create individual arrays like...
$arr = array($bet_option_id => $bet_option_name);
If you first create an empty array ( like you do with $result)
$arr = array();
and then add each item in using
$arr[$bet_option_id] = $bet_option_name;
Then you don't need to manipulate the array after - just create it as you want it in the first place.
You could either do like Nigel Ren suggested which is the most elegant solution
In case that you do not have arrays that their keys are entirely numeric you may use array_merge. The quote following is from PHP array-merge
Example #2 Simple array_merge() example
$array1 = array();
$array2 = array(1 => "data");
$result = array_merge($array1, $array2);
Don't forget that numeric keys will be renumbered!
Array
(
[0] => data
)
Alternatively you can always join arrays together like this
$a1 = [ 997650802 => 'Over 2.5' ];
$a2 = [ 997650807 => 'Yes' ];
var_dump( $a1 + $a2 ); // result is [997650802 => 'Over 2.5',997650807 => 'Yes']
You can check more about Array Types and Array Operators

PHP Convert multidimensional array to match format of another

I have two arrays, one is generated by using explode() on a comma separated string and the other is generated from result_array() in Codeigniter.
The results when doing print_r are:
From explode():
Array
(
[0] => keyword
[1] => test
)
From database:
Array
(
[0] => Array
(
[name] => keyword
)
[1] => Array
(
[name] => test
)
)
I need them to match up so I can use array_diff(), what's the best way to get them to match? Is there something other than result_array() in CI to get a compatible array?
You could create a new array like this:
foreach($fromDatabase as $x)
{
$arr[] = $x['name'];
}
Now, you will have two one dim arrays and you can run array_dif.
$new_array = array();
foreach ($array1 as $line) {
$new_array[] = array('name' => $line);
}
print_r($new_array);
That should work for you.

How to convert a 2-dim array of strings into 1-dim array of trimmed, unique values?

I have an array whose values are all arrays of a specific format that looks like this:
Array
(
[0] => Array
(
[0] => '8227'
[1] => ' 8138'
)
[1] => Array
(
[0] => '8227'
[1] => ' 8138'
[2] => ' 7785'
)
)
and I would like to have this:
Array
(
[0] => 8227
[1] => 8138
[2] => 7785
)
How can I do this ?
$result = array();
foreach ($input as $sub) { // Loop outer array
foreach ($sub as $val) { // Loop inner arrays
$val = trim($val);
if (!in_array($val, $result)) { // Check for duplicates
$result[] = $val; // Add to result array
}
}
}
$result = array();
foreach($array as $arr){
$result = array_merge($result, $arr);
}
$result = array_unique($result);
array_merge_recursive() can be used to flatten the array. Then, array_unique() to get the unique values, with array_values() to "reindex" the resultant array.
$flat = call_user_func_array('array_merge_recursive', $subject);
$uniq = array_values(array_unique($flat));
<?php
$array = array(
0 => array(
0 => 8227,
1 => 8138
),
1 => array(
0 => 8227,
1 => 8138,
2 => 7785
)
);
$newArray = array();
array_walk_recursive($array, function($item, $key) use(&$newArray) {
if(!in_array($item, $newArray)) {
$newArray[] = $item;
}
});
print_r($newArray);
?>
I don't like the idea of iterated calls of in_array() since it can cause a bit of drag on big arrays.
Now, my methods to follow are probably not going to set any speed records (I didn't bother to benchmark), but I thought I would post a couple of unorthodox approaches in case they may inspire future readers.
Method #1:
convert the multi-dimensional array to a json string
split the string on all non-digital substrings (this also trims the values)
eliminate duplicates using array_flip()
re-index the resultant array using array_keys() (output values are integer-type)
Method #2:
convert the multi-dimensional array to a json string
extract the words (which in this case include numbers and there aren't any letters to worry about)
eliminate duplicates using array_flip()
reindex the resultant array using array_keys() (output values are integer-type)
Code: (Demo)
$array = [['8227', '8138'], [' 8227', ' 8138', ' 7785']];
echo "regex method: ";
var_export(
array_keys(
array_flip(
preg_split(
'/\D+/',
json_encode($array),
0,
PREG_SPLIT_NO_EMPTY
)
)
)
);
echo "\n\nnon-regex method: ";
var_export(
array_keys(
array_flip(
str_word_count(
json_encode($array),
1,
'0..9'
)
)
)
);
Output:
regex method: array (
0 => 8227,
1 => 8138,
2 => 7785,
)
non-regex method: array (
0 => 8227,
1 => 8138,
2 => 7785,
)
If either of these methods perform well, it will be because they don't make iterated function calls.
p.s. Okay, because I was curious, I just did a very small / unofficial speed test on my two methods and DaveRandom's method (only 1000 iterations using the OP's data - I didn't want to abuse 3v4l.org) and...
Method #1 ran about as fast as Method #2
Both Method #1 and Method #2 ran faster than DaveRandom's method.
Again, I'll state that fabricated tests for micro-optimization may be pointless and real tests should be done on your REAL data IF it is actually important. If you merely prefer the logical flow of another answer on this page, I totally respect that.

How to compare arrays and extract the difference?

I have two arrays that I would like to compare and ultimately wind up with a single array with everything combined, having no duplicates. Can someone please tell me which function I should use? There are so many that it's a bit confusing.
$array1[]['name'] = 'Kim, Jones';
$array1[]['name'] = 'Jim, Miller';
array1 is an array I built that I want added to an array coming from the database. The key in the second array is also named "name". Thanks.
EDIT:
I managed to merge these two arrays but I can still see duplicates.
This is what the first array looks like:
Array
(
[0] => Array
(
[WNumber] => ADMIN
[Name] => Tim, Cooley
[Employer] => CalPERS
[Student] => 1
[Perm] => 1
[QA] => 0
[Supervisor] => 1
[RQW] => 0
)
My second array is built like this:
$add_names[]['Name']='Jim, Jones';
I just want to add $add_names to the first array WHERE there are no duplicates.
I'm tempted to sell you on CakePHP, since it has a number of functions that makes this easy in its "Set" class. Your problem is that you have the results in a nested array. A simple "array_unique" does not work in a nested array.
I'd do it the old fashioned way...
$array1[]['name'] = 'Kim, Jones';
$array1[]['name'] = 'Jim, Miller';
$array2[]['name'] = 'Kim, Jones';
$array2[]['name'] = 'Jimbo, Miller';
$array2[]['name'] = 'Jim, Jones';
$new_array=array_merge($array1, $array2);
$out_array = array();
$key_array = array();
foreach($new_array as $i => $row) {
if (empty($key_array[$row['name']])) {
$out_array[] = $row;
}
$key_array[$row['name']] = 1;
}
print_r($out_array);
This code works for me...
I think you'll need to use a combination of array_merge (adds the two arrays together) and array_unique (removes duplicate values).
$resulting_array = array_unique(array_merge($array1, $array2));
Note that array_unique will not work correctly when using multi-dimensional arrays, so if your array data looks the way you put it in your question, you'll have to think of a way around that. One of the comments on the array_unique page suggests serialize'ing all array values before running array_unique on it. Afterwards you'd just run unserialize on all array elements. Note that this can mean a performance hit if you have a big array, so you might want to consider avoiding multi-dimensional arrays in this scenario.
Something like this:
$merged_array = array_merge($array1, $array2);
$serialized_array = array_map("serialize", $merged_array);
$filtered_array = array_unique($serialized_array);
$final_array = array_map("unserialize", $filtered_array);
There isn't a direct function for handling what you are looking for in php, probably you need to write a function for it.
What I understood from your question is that you have 2 arrays :
$a = array( array( 'name' => 'Omid' ), 12 );
$b = array( array( 'name' => 'testing' ) );
and you want to merge them to get
$merge = array( array( 'name' => 'testing' ), 12 );
if that's what you want then you might want to take a look at this comment array merge recursive which leads to this code :
function array_merge_recursive_distinct ( array &$array1, array &$array2 )
{
$merged = $array1;
foreach ( $array2 as $key => &$value )
{
if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) )
{
$merged [$key] = array_merge_recursive_distinct ( $merged [$key], $value );
}
else
{
$merged [$key] = $value;
}
}
return $merged;
}
Does php's array_diff() do what you want?
http://us.php.net/manual/en/function.array-diff.php
or more likely array_diff_assoc:
http://us.php.net/manual/en/function.array-diff-assoc.php
Does array_diff work for you?
Description
array array_diff ( array $array1 , array $array2 [, array $ ... ] )
Compares array1 against array2 and returns the difference.

Categories