Array_merge_recursive gives me repeat data, how to remove it - php

I have the following 2 arrays that I'm trying to merge recursively so that I don't lose data, but I also don't want any data repeated.
$a = array(
'group1' => array(
'names' => array(
'g1name1',
'g1name2'
)
),
'group2' => array(
'names' => array(
'g2name1'
)
)
);
$b = array(
'group1' => array(
'names' => array(
'g1name1',
'g1name3'
),
'extras' => array(
'g1extra1'
)
),
'group3' => array(
'names' => array(
'g3name1'
)
)
);
I'm using array_merge_recursive($a, $b); which works fine for group2 and group3 because they exist in either $a or $b, but group1 is giving me a problem because it has some duplicate data in both $a and $b. This is what I'm getting after I merge recursively. Notice that in names, g1name is listed twice, once from $a and once from $b.
'group1' =>
array
'names' =>
array
0 => string 'g1name1'
1 => string 'g1name2'
2 => string 'g1name1'
3 => string 'g1name3'
'extras' =>
array
0 => string 'g1extra1'
1 => string 'g1extra2'
'group2' => ....
'group3' => ....
I tried array_unique like this array_unique(array_merge_recursive($a, $b)) but it's giving me strange results (doesn't fix the repeat problem and deletes group2 and group3 entirely).

Use array_replace_recursive instead of array_merge_recursive.

The the following should work for you:
array_walk($arr, function(&$data, $key) {
foreach ($data as &$arr) {
$arr = array_values(array_unique($arr));
}
});
Result:
Array
(
[group1] => Array
(
[names] => Array
(
[0] => g1name1
[1] => g1name2
[2] => g1name3
)
[extras] => Array
(
[0] => g1extra1
)
)
[group2] => Array
(
[names] => Array
(
[0] => g2name1
)
)
[group3] => Array
(
[names] => Array
(
[0] => g3name1
)
)
)

Sadly, array_replace_recursive (PHP 5.3.0)­Docs does not work (Demo).
Luckily Tim Cooper pointed that out and made some suggestion. I was not very creative with my new suggestion, so it's highly influenced by his solution:
$result = array_merge_recursive($a, $b);
array_walk($result, function(&$v) {
$v = array_map('array_unique', $v);
});
New Demo

Related

Merge PHP array having same keys different values

I am trying to merge arrays with the same keys with different values, like below.
Input:
$array1 = array('1933' => array(
'nid' => '492811',
'title' => 'NEW TITLE',
'field_link_single_url' => 'abc',
'field_link_single_title' => 'test'
));
$array2 = array('1933' => array(
'nid' => '492811',
'title' => 'NEW TITLE',
'field_link_single_url' => 'xyz',
'field_link_single_title' => 'abcd'
));
Expected output to be:
Array
(
[nid] => 492811
[title] => NEW TITLE
[field_link_single_url] => [
[0] => 'abc',
[1] => 'xyz'
]
[field_link_single_title] => [
[0] => 'test',
[1] => 'abcd'
]
)
I have tried array_merge and array_merge_recursive but it does not work as expected.
Output of array_merge_recursive($array1[1933], $array2[1933]) it is creating duplicates keys having same value
Array
(
[nid] => Array
(
[0] => 492811
[1] => 492811
)
[title] => Array
(
[0] => Hal Louchheim
[1] => Hal Louchheim
)
[field_link_single_url] => Array
(
[0] => abc
[1] => xyz
)
[field_link_single_title] => Array
(
[0] => test
[1] => abcd
)
)
I made some assumption. If these assumptions are not valid, you should add some additional checks:
Both $array1 and $array2 are really arrays
Both $array1 and $array2 have the exact same keys
The values inside $array1 and $array2 are primitive types, not complex objects (the === operator would not work to compare objects or arrays)
function mergeArrayValues($array1, $array2) {
$output = [];
foreach($array1 as $key => $value) {
$output[$key] = $array1[$key] === $array2[$key]
? $array1[$key]
: [ $array1[$key], $array2[$key] ]
}
return $output;
}
mergeArrayValues($array1[1933], $array2[1933])

How to store a multidimentional array to simple array

I have an Array as seen below.
Array
(
[0] =>
[key-1] => Array
(
[key-1-1] => 33
[key-1-2] => 22
)
[key-2] => -1
[key-3] => Array
(
[data] => Array
(
[other_data] => Array
(
[0] => data1
[1] => data2
)
)
)
[key-4] => data3
[key-5] => data4
)
I need to convert these in simpler form of end values as given below and save to an external php file using file_put_contents . I am trying for hours and I tried var_export, multiple foreach and got some degree of success, but not exactly what I want.
$value['key-1-1'] = '33';
$value['key-1-2'] = '22';
$value['other_data'] = array('data1', 'data2');
$value['key-4'] = 'data3';
$value['key-5'] = 'data4';
Can someone help with achieving it ?
You can get somewhat near to your desired output with array_walk_recursive. The troublesome keys are the numeric ones.
If you only have one other_data sub arrays, you could slightly adjust the output below. You'll get overwritten values for like numeric keys. So this method really depends on your data.
<?php
$data =
array
(
'0' =>'',
'key-1' => array
(
'key-1-1' => 33,
'key-1-2' => 22
),
'key-2' => -1,
'key-3' => array
(
'data' => array
(
'other_data' => array
(
'0' => 'data1',
'1' => 'data2'
)
)
),
'key-4' => 'data3',
'key-5' => 'data4'
);
array_walk_recursive($data, function($v, $k) use (&$result) {
$result[$k] = $v;
});
var_export($result);
Output:
array (
0 => 'data1',
'key-1-1' => 33,
'key-1-2' => 22,
'key-2' => -1,
1 => 'data2',
'key-4' => 'data3',
'key-5' => 'data4',
)

PHP list arrays

Is it possible to list arrays from an array with function?
I have configuration array of a plugin in which I wast to call function which will list arrays from array.
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something')
)
I made function:
function config(){
$a = array('id'=>'someidA','id'=>'somethingA');
$b = array('id'=>'someidB','id'=>'somethingB');
return array($a,$b);
}
When call config() function in array I get:
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array(
array('id'=>'someidA','id'=>'somethingA'),
array('id'=>'someidB','id'=>'somethingB')
)
)
But I need:
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someidA','id'=>'somethingA'),
array('id'=>'someidB','id'=>'somethingB')
)
I know this works:
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
list($a,$b)=config(),
$a,$b,
)
But it does not help me too much, as sometime there are lot of $a,$,$c,$d etc, so it will be the best if somehow function could list those arrays.
Is there some ways to get rid of that container array and list arrays directly to another array?
array_merge will work for you. It merges 2 or more arrays into a single array.
<?php
$arr = array(
'fields' => array(
array('id1'=>'someid','id2'=>'something'),
array('id1'=>'someid','id2'=>'something'),
array('id1'=>'someid','id2'=>'something')
)
);
function config(){
$a = array('id1'=>'someidA','id2'=>'somethingA');
$b = array('id1'=>'someidB','id2'=>'somethingB');
return array($a,$b);
}
$config_arr = config();
$arr['fields'] = array_merge($arr['fields'], $config_arr);
print_r($arr);
?>
Working Example.
OUTPUT
Array
(
[fields] => Array
(
[0] => Array
(
[id1] => someid
[id2] => something
)
[1] => Array
(
[id1] => someid
[id2] => something
)
[2] => Array
(
[id1] => someid
[id2] => something
)
[3] => Array
(
[id1] => someidA
[id2] => somethingA
)
[4] => Array
(
[id1] => someidB
[id2] => somethingB
)
)
)
As an alternative to Samir's solution...
By using the "splat operator" (...) to unpack the returned array from config() and then array_push() to append both subarrays, you can achieve the desired result.
Code: (Demo)
$config = [
'fields' => [
['id1' => 'someid', 'id2' => 'something'],
['id1' => 'someid', 'id2' => 'something'],
['id1' => 'someid', 'id2' => 'something']
]
];
function config() {
$a = ['id1' => 'someidA','id2' => 'somethingA'];
$b = ['id1' => 'someidB','id2' => 'somethingB'];
return [$a, $b];
}
array_push($config['fields'], ...config());
var_export($config);

php create new array adding distinct values from existing one

Suppose i have 2 arrays:
$array1 =( [0] => Array ( [user] => 'aaa' [count] => '123' )
[1] => Array ( [user] => 'bbb' [count] => '456' )
[2] => Array ( [user] => 'ccc' [count] => '789' ) );
$array2= ( [0] => aaa)
[1] => ccc );
I would like to search values from second array in first array and create the third array that will contain all elements from first array, like this:
$array3 =( [0] => Array ( [user] => 'aaa' [count] => '123' )
[1] => Array ( [user] => 'ccc' [count] => '789' ) );
Please help. Thank you in advance
(sorry for bad english)
$array1 = array(
array( 'user' => 'aaa', 'count' => 123 ),
array( 'user' => 'bbb', 'count' => 456 ),
array( 'user' => 'ccc', 'count' => 789 ),
);
$array2 = array('aaa', 'ccc');
var_dump(array_filter($array1, function($el) use($array2) {
return in_array($el['user'], $array2);
}));
It preserves keys, you can reset them if needed. Or with foreach loop
$out = array();
foreach($array1 as $el)
{
if (in_array($el['user'], $array2))
$out[] = $el;
}
var_dump($out);
Can try using foreach(). Example here...
$array3 = array();
foreach($array2 as $search){
foreach($array1 as $val){
if($search == $val['user']){
$array3[] = $val;
}
}
}
print_r($array3);

filter array after merging keys of one array

I am trying to create filtered array 3 using array 1 and array 2.
ARRAY 1
Array (
[title] => value
[title2] => value2
[title3] => value3
)
ARRAY 2
Array (
[0] => Array ( [id] => 20 [title2] => value2 [otherColumn1] => otherValue1)
[1] => Array ( [id] => 21 [title4] => value4 [otherColumn3] => otherValue3)
)
Desired Result after applying the intersection method:
ARRAY 3
Array ( [title2] => value2 )
So far I am unable to achieve the result because array 1 and 2 have non-matching structures. I have tried different techniques but I am unable compare them due to structure differences.
if (!empty($data1['array2'][0])) {
foreach ($data1['array2'] as $key) {
// $filtered= array_intersect($array1,$key);
// print_r($key);
}
// $filtered= array_intersect($array1,$data1['array2']);// if i use $data1['array2'][0] it filters fine but just one row
// print_r($filtered);
}
Any help would be much appreciated. Thank you.
Given the arrays:
$arr = array('title' => 'value', 'title2' => 'value2', 'title3' => 'value3');
$arr2 = array (
0 => array ( 'id' => '20', 'title2' => 'value2', 'otherColumn1' => 'otherValue1'),
1 => array ( 'id' => '21', 'title4' => 'value4', 'otherColumn3' => 'otherValue3'));
You can get your filtered array with this:
$merged = call_user_func_array('array_merge', $arr2);
$filtered = array_intersect($arr, $merged);
If you want to intersect just according to the keys you can use this instead:
$filtered = array_intersect_key($arr, $merged);
you can remove structural difference in the following way
$arr1 = array (
0 => array('title' => 'value', 'title2' => 'value2', 'title3' => 'value3'));
$arr2 = array (
0 => array ( 'id' => '20', 'title2' => 'value2', 'otherColumn1' => 'otherValue1'),
1 => array ( 'id' => '21', 'title4' => 'value4', 'otherColumn3' => 'otherValue3'));

Categories