merge arrays without reindexing keys - php

I have two arrays that I want to merge recursively, so adding arrays is not an option. This is simple example without multilevels to demonstrate the problem:
$a1 = Array(
5 => 'pronoun'
)
$a2 = Array(
2 => 'verb',
3 => 'noun'
)
$r = array_merge_recursive($a1, $a2)
And I want to get that resulting array:
Array(
5 => 'pronoun'
2 => 'verb',
3 => 'noun'
)
My problem is that array_merge_recursive function reindixes keys, and I get the following:
Array(
0 => 'pronoun'
1 => 'verb',
2 => 'noun'
)
I understand that's happening because all my keys are numeric. So I tried to make them string when adding but it doesn't seem to be working properly:
$a1[(string)7] = 'some value';
The key - 7 - is still number, or at least that's how it is displayed in debugger - $a1[7] and not $a1['7']. Any advice?
EDIT:
Addition of arrays is not an option. Please see why. I have two multilevel arrays:
$a1 = array (
1 => array (
1 => "man1",
2 => "man"
),
2 => array (
1 => "run",
2 => "nice"
)
);
$a2 = array(
2 => array (
1 => "to observe",
2 => "to examine visually"),
3 => array(
1 => "look nice",
2 => "appear, seem to be"));
$r = $a1 + $a2;
What I expect is the following:
$r = Array(
...
2 => array(
1 => array("run", "to observe")
2 => array("nice", "to examine visually")
));
But instead the options for the key 2 from the second array is not added:
$r = Array(
...
2 => array(
1 => "run",
2 => "nice"
));

you can just use $a1+$a2 to get your result
$a1 = array(
5 => 'pronoun'
);
$a2 = array(
2 => 'verb',
3 => 'noun'
);
print_r($a1+$a2);
For recursive array
$a1 = array(
5 => 'pronoun'
);
$a2 = array(array('a', 'z'), array(2 => 'p', 'q'));
print_r($a1+$a2);
Result is
Array
(
[5] => pronoun
[0] => Array
(
[0] => a
[1] => z
)
[1] => Array
(
[2] => p
[3] => q
)
)
is this what you want to achieve?

This should apply to your particular problem:
function assoc_merge(array $a, array $b)
{
$r = array();
foreach ($a as $key => $val) {
if (array_key_exists($key, $b) && is_array($val) == is_array($b[$key])) {
if (is_array($val)) {
$r[$key] = assoc_merge($a[$key], $b[$key]); // merge array
} else {
$r[$key] = array($val, $b[$key]); // merge entry
}
} else {
$r[$key] = $val; // just copy
}
}
return $r + $b; // add whatever we missed
}
print_r(assoc_merge($a1, $a2));

You can always try the manual case.
function merge () { // takes any number of arguments
$arrays = func_get_args();
$result = array();
foreach ($arrays as $array)
foreach ($array as $key => $item)
if (is_array($item))
$result = merge($result, $item);
else
$result[$key] = $item;
return $result;
Sure, it's slow, but it will work.

$a1 = array(
5 => 'pronoun'
);
$a2 = array(
2 => 'verb',
3 => 'noun'
);
foreach($a2 as $key=>$value) {
$a1[$key] = $value;
}
print_r($a1);

<?php
$a = [ 5 => 'pronoun'];
$b = [ 2 => 'verb', 3 => 'noun'];
$m = array_merge(array_keys($a), array_keys($b));
$final = array_combine($m, array_merge_recursive($a, $b));
print_r($final);

Related

cakephp find the array elements by meeting the conditions between two arrays?

I have two arrays. One array consists of Id & another array consists of the values & keys. For example. I have a variable called Fruit_id, which consists of:
array(
'fruit_id' => array(
(int) 0 => '3',
(int) 1 => '4'
)
)
and another array called fruits, which consists of:
array(
'values' => array(
(int) 1 => ' Apple',
(int) 2 => 'Banana',
(int) 3 => 'Orange',
(int) 4 => 'Mango'
),
'keys' => array(
(int) 0 => (int) 1,
(int) 1 => (int) 2,
(int) 2 => (int) 3,
(int) 3 => (int) 4
)
)
So, based on fruit_id, I want to have Orange & Mango stored in a variable. How can this be achieved?
as per my understanding you can try below code
$fruits = array();
foreach ($array1['fruit_id'] as $key1 => $value1)
{
foreach ($array2['values'] as $key2 => $value2)
{
if ($value1 == $key2)
{
$fruits[$value1] = $value2;
}
}
}
print_r($fruits);
This will return Array ( [3] => Orange [4] => Mango )
Let me know if this helps you out or any changes needed
You could achieve this easily without even using any loop. Use array_filter() instead.
$array1 = array("fruit_id" => array(3, 4));
$array2 = array(
"values" => array(1 => "Apple",2 => "Banana",3 => "Orange", 4 => "Mango"),
"keys" => array(1,2,3,4)
);
/* Filter elements from $array2['values'] whose keys are present in $array1['fruit_id'] */
$result = array_filter($array2['values'], function($v, $k) use ($array1){
return in_array($k, $array1['fruit_id']);
}, ARRAY_FILTER_USE_BOTH);
echo implode(' & ', $result); // Convert array to string separated by '&'

How to remove all items of array except specific one?

I have a variable which is containing these nested arrays:
echo $var;
/* Output:
Array(
[0] => Array
(
[id] => 1
[box] => 0
)
[2] => Array
(
[id] => 2
[box] => 0
)
[3] => Array
(
[id] => 3
[box] => 1
)
) */
Now I want to remove all items of array above except $numb = 2; (the value of id). I mean I want this output:
echo newvar;
/* Output:
Array(
[2] => Array
(
[id] => 2
[box] => 0
)
) */
How can I do that?
Actually I can do a part of it by using if statement and array_shift() function:
foreach($var as $key => $val) {
if($val["id"] != 2) {
array_shift($var);
}
}
But the output of code above isn't want I need.
You can use a slightly different loop.
foreach ($var as $item) {
if ($item['id'] == 2) {
$newvar = $item;
break;
}
}
You could also use array_filter
$id = 2;
$newvar = array_filter($var, function($x) use ($id) { return $x['id'] == $id; });
but it would most likely be less efficient as it would have to check every element of the array.
I'm wondering how much context would help us with answering your question... Here is an answer to what you asked:
$newArray = array($var[2]);
You could just make a new array:
$oldArray = array(0 => 'a', 1 => 'b', 2 => 'c', 3=> 'd');
$index = 2;
$newArray = array($index => $oldArray[$index]);
// or even
$newArray = [$index => $oldArray[$index]];
If you don't need to preserve the index you can just do:
$newArray = [$oldArray[$index]];
array_reduce() would also do the job:
$array = [
['id' => 1, 'box' => 0],
['id' => 2, 'box' => 0],
['id' => 3, 'box' => 1]
];
$id = 2;
$result = array_reduce ($array, function ($carry, $item) use ($id) {
if ( $item['id'] === $id )
$carry[$item['id']] = $item;
return $carry;
}, []);

PHP Merge 2 arrays if value is found and create new value

i want to compare 2 arrays. If a value from $a ist found is $b there should be make a new value in $a like [found] => true.
Array $a:
Array
(
[1] => Array
(
[grpID] => 1
[groupname] => Marketing
)
[2] => Array
(
[grpID] => 2
[groupname] => Vertrieb
)
[4] => Array
(
[grpID] => 4
[groupname] => Produktion
)
)
Array $b:
Array
(
[1] => Array
(
[usrID] => 23
[grpID] => 1
)
)
So now i want to compare these two.
The result should look like the following, because $b[1]['grpID'] was like in $a[1]['grpID']:
Array $c (or $a as manipulated?):
Array
(
[1] => Array
(
[grpID] => 1
[groupname] => Marketing
[found] => true
)
[2] => Array
(
[grpID] => 2
[groupname] => Vertrieb
[found] => false
)
)
The size of $b may vary so i don't think i can work with a for-loop, can i?
Sorry, i've got no code so far as i don't have an idea how to start.
Thanks in advance.
Best regards
Do it with an temporary array $temp.
$a = array();
$b = array();
$c = array();
$tmp = array();
$a[1] = array('grpID' => 1, 'groupname' => 'Marketing');
$a[2] = array('grpID' => 2, 'groupname' => 'Vertrieb');
$a[4] = array('grpID' => 4, 'groupname' => 'Produktion');
$b[1] = array('usrID' => 23, 'grpID' => 1);
foreach ($b as $key => $value) {
$tmp[] = $value['grpID'];
}
foreach ($a as $key => $value) {
$c[] = array_merge($value, array('found' => (in_array($value['grpID'], $tmp) ? 'true' : false)));
}
Checkout the following code
<?php
$a = array(
array(
'grpID' => 1,
'groupname' => 'Marketing'
),
array(
'grpID' => 2,
'groupname' => 'Vertrieb'
),
array(
'grpID' => 5,
'groupname' => 'Produktion'
)
);
$b = array(
array(
'grpID' => 1,
'usrID' => 23
)
);
$c = array();
for ($i = 0; $i < count($a); $i++)
{
$tmp = $a[$i];
$tmp['found'] = FALSE;
for ($j = 0; $j < count($b); $j++)
{
if ($tmp['grpID'] === $b[$j]['grpID'])
{
$tmp['found'] = TRUE;
break;
}
}
array_push($c, $tmp);
}
// Final output
print_r($c);
?>
There are a few different ways to do this, I toyed with the idea of using array_walk and using a object orientated approach. The way below is the simplest to implement but if I were doing this on a system of my own I would probably go object orientated for cleaner code and better maintenance.
here are the help pages for array_walk http://uk1.php.net/array_walk just in case you wanted to look at another way.
$foundGroups = array();
//set all found values to false
foreach ($a as $group) {
$group['found'] = false;
}
foreach ($b as $user) {
$groupToFind = $user['grpID'];
// This is to limit the number of times we do this, there is no point
// in looking for the same group twice
if (!in_array($groupToFind, $foundGroups)) {
foreach ($a as $group) {
if ($group['grpID'] == $groupToFind) {
$group['found'] = 'true';
$foundGroups[] = $groupToFind;
}
}
}
}

find duplicate value in multi-dimensional array

From a function I am given a multidimensional array like this:
array(
[0] => array(
[0] => 7,
[1] => 18
),
[1] => array(
[0] => 12,
[1] => 7
),
[2] => array(
[0] => 12,
[1] => 7,
[2] => 13
)
)
I need to find duplicate values in the 3 arrays within the main array. For example, if value 7 repeats in the 3 arrays, return 7.
<?php
$array = array(array(7,18), array(12,7), array(12, 7, 13));
$result = array();
$first = $array[0];
for($i=1; $i<count($array); $i++){
$result = array_intersect ($first, $array[$i]);
$first = $result;
}
print_r($result);//7
?>
use my custom function
function array_icount_values($arr,$lower=true) {
$arr2=array();
if(!is_array($arr['0'])){$arr=array($arr);}
foreach($arr as $k=> $v){
foreach($v as $v2){
if($lower==true) {$v2=strtolower($v2);}
if(!isset($arr2[$v2])){
$arr2[$v2]=1;
}else{
$arr2[$v2]++;
}
}
}
return $arr2;
}
$arr = array_icount_values($arry);
echo "<pre>";
print_r($arr);
exit;
OUPUT
Array
(
[7] => 3
[18] => 1
[12] => 2
[13] => 1
)
hope this will sure help you.
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
use this code
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
You will need to loop through the first array, and for each value in it, see if it is in_array().
$findme = array();
foreach ($array[0] as $key => $value)
{
if (in_array ($value, $array[1]) && in_array ($value, $array[2]))
{
$findme[] = $value;
}
}
// $findme will be an array containing all values that are present in all three arrays (if any).

How can I merge PHP arrays?

I have two arrays of animals (for example).
$array = array(
array(
'id' => 1,
'name' => 'Cat',
),
array(
'id' => 2,
'name' => 'Mouse',
)
);
$array2 = array(
array(
'id' => 2,
'age' => 321,
),
array(
'id' => 1,
'age' => 123,
)
);
How can I merge the two arrays into one by the ID?
#Andy
http://se.php.net/array_merge
That was my first thought but it doesn't quite work - however array_merge_recursive might work - too lazy to check right now.
This does what Erik suggested (id no. as array key) and merges vlaues in $array2 to $results.
$results = array();
foreach($array as $subarray)
{
$results[$subarray['id']] = array('name' => $subarray['name']);
}
foreach($array2 as $subarray)
{
if(array_key_exists($subarray['id'], $results))
{
// Loop through $subarray would go here if you have extra
$results[$subarray['id']]['age'] = $subarray['age'];
}
}
First off, why don't you use the ID as the index (or key, in the mapping-style array that php arrays are imo)?
$array = array(
1 => array(
'name' => 'Cat',
),
2 => array(
'name' => 'Mouse',
)
);
after that you'll have to foreach through one array, performing array_merge on the items of the other:
foreach($array2 as $key=>$value) {
if(!is_array($array[$key])) $array[$key] = $value;
else $array[$key] = array_merge($array[key], $value);
}
Something like that at least. Perhaps there's a better solution?
<?php
$a = array('a' => '1', 'b' => array('t' => '4', 'g' => array('e' => '8')));
$b = array('c' => '3', 'b' => array('0' => '4', 'g' => array('h' => '5', 'v' => '9')));
$c = array_merge_recursive($a, $b);
print_r($c);
?>
array_merge_recursive — Merge two or more arrays recursively
outputs:
Array
(
[a] => 1
[b] => Array
(
[t] => 4
[g] => Array
(
[e] => 8
[h] => 5
[v] => 9
)
[0] => 4
)
[c] => 3
)
#Andy
I've already looked at that and didn't see how it can help merge multidimensional arrays. Maybe you could give an example.
#kevin
That is probably what I will need to do as I think the code below will be very slow.
The actual code is a bit different because I'm using ADOdb (and ODBC for the other query) but I'll make it work and post my own answer.
This works, however I think it will be very slow as it goes through the second loop every time:
foreach($array as &$animal)
{
foreach($array2 as $animal2)
{
if($animal['id'] === $animal2['id'])
{
$animal = array_merge($animal, $animal2);
break;
}
}
}
foreach ($array as $a)
$new_array[$a['id']]['name'] = $a['name'];
foreach ($array2 as $a)
$new_array[$a['id']]['age'] = $a['age'];
and this is result:
[1] => Array
(
[name] => Cat
[age] => 123
)
[2] => Array
(
[name] => Mouse
[age] => 321
)
<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
With PHP 5.3 you can do this sort of merge with array_replace_recursive()
http://www.php.net/manual/en/function.array-replace-recursive.php
You're resultant array should look like:
Array (
[0] => Array
(
[id] => 2
[name] => Cat
[age] => 321
)
[1] => Array
(
[id] => 1
[name] => Mouse
[age] => 123
)
)
Which is what I think you wanted as a result.
I would rather prefer array_splice over array_merge because of its performance issues, my solution would be:
<?php
array_splice($array1,count($array1),0,$array2);
?>
$new = array();
foreach ($array as $arr) {
$match = false;
foreach ($array2 as $arr2) {
if ($arr['id'] == $arr2['id']) {
$match = true;
$new[] = array_merge($arr, $arr2);
break;
}
}
if ( !$match ) $new[] = $arr;
}

Categories