php - merge arrays keeping keys and incrementing - php

I've been trying to figure this one out all day but cant seem to explain, or get across what I'm trying to achieve. Lets say I have 2 arrays:
Array
(
[1] => Array
(
[2] => Dashboard
)
)
and
Array
(
[1] => Array
(
[3] => Toasts
)
)
What I want to be able to do is merge the 2 arrays as follows:
Array
(
[1] => Array
(
[2] => Dashboard,
[3] => Toasts
)
)
But, if I have something like this:
Array
(
[1] => Array
(
[2] => Dashboard
)
)
Array
(
[1] => Array
(
[2] => Toasts
)
)
I dont want to loose the value of the overriding element but increment it like so
Array
(
[1] => Array
(
[2] => Dashboard,
[3] => Toasts
)
)
I have tried everything from array merge, recursive merge and even eval but I just can get my head around it. Has anyone come across this before? a function I haven't found?

You should be using $array['indexname'] = 'value';. array_merge() or array_push() doesn't maintain the values having same/associative keys while merging, because there is no way to determine the next key.

Maybe not a real answer but just a way to escape overwriting;
$a1 = array(array(2 => 'Dashboard'));
$a2 = array(array(3 => 'Toasts'));
$a3 = array(array(3 => 'Foo'));
$array = array();
foreach (array_merge($a1, $a2, $a3) as $a) {
foreach ($a as $i => $value) {
if (!isset($array[$i])) {
$array[$i] = $value;
} else {
$array[] = $value;
}
}
}
print_r($array);
Array
(
[2] => Dashboard
[3] => Toasts
[4] => Foo
)

Related

Using array_flip() to return an array

I have an array:
$input = array(1,2,3,4,6,5,3,6)
and I want the key/value pairs to be flipped.
This can be done by using the array_flip() function.
$flipped = array_flip($input)
If in the original array has 2 or more same values (in this case number 6)how can I return it in an array?
array= ([1]=0,[2]=>1,[4]=>2,[6]=>array(3,6),[5]=>4,[3]=>5)
I tried to use array_count_values() but can't figure out how to do it?
You cannot do that using the array_flip() function. Probably you look for something like that:
<?php
function array_flip_and_collect($input) {
$output = [];
foreach ($input as $key=>$val) {
$output[$val][] = $key;
}
return $output;
}
$input = array(1,2,3,4,6,5,3,6);
print_r(array_flip_and_collect($input));
The output:
Array
(
[1] => Array
(
[0] => 0
)
[2] => Array
(
[0] => 1
)
[3] => Array
(
[0] => 2
[1] => 6
)
[4] => Array
(
[0] => 3
)
[6] => Array
(
[0] => 4
[1] => 7
)
[5] => Array
(
[0] => 5
)
)
Note that the output differs slightly from what you suggested in your question. That is by purpose because this appears more logical to me. If you really want that keys with only one element really are scalars and not arrays with one element, then you have to add an additional conversion step to the code.

Remove array from a multidimensional array if the same value exists in another multidimensional array

I have two arrays like
Array
(
[0] => Array
(
[id] => 1
[controller] => users
[action] => index
)
[1] => Array
(
[id] => 1
[controller] => users
[action] =>
)
[2] => Array
(
[id] => 1
[controller] => users
[action] => login
)
)
Array
(
[0] => Array
(
[id] => 1
[controller] => users
[action] => index
)
[1] => Array
(
[id] => 1
[controller] => users
[action] =>
)
[2] => Array
(
[id] => 1
[controller] => users
[action] => logout
)
)
I want to remove complete nested array from 1st array if a match is found in 2nd array (Based on keys ['controller'] &&['action']). So in the first array only the 3rd [2] array is unique.
The output should be like :
Array
(
[0] => Array
(
[id] => 1
[controller] => users
[action] => login
)
)
Please Note
Please note that the 2nd array doesn't necessary to be in same order as first. As opposed in my question where the first two arrays of each array are identical.
What i have tried is :
$result = array();
for($i=0; $i < count($a); $i++)
{
$result[] = array_diff($a[$i], $b[$i]);
}
print_r($result); // This doesn't give required output. It removes every thing and return like
Array
(
[0] => Array
(
)
[1] => Array
(
)
[2] => Array
(
[action] => login
)
)
Have a look at this answer. I think it'll do exactly what you need it to.
There are numerous ways you could go about this. Here's one that I think would be pretty simple.
First up, setup a new array based on $a, indexing it by the controller and action attributes.
$final = array();
foreach($a AS $item) {
$final[$item['controller'] . $item['action']] = $item;
}
Now you can loop through the second array, removing any matching items.
foreach($b AS $item) {
unset($final[$item['controller'] . $item['action']]);
}
Now $final should be the array you want.
Working example: http://3v4l.org/JtUkN
Here is my own working solution
for($i=0; $i < count($data); $i++)
{
foreach($this->existing_data as $v)
{
if( ($v['controller'] == $data[$i]['controller']) && ($v['action'] == $data[$i]['action']) )
{
unset($data[$i]);
break;
}
}
}

Sort Multi Dimensional Array by its keys from another arrays values

This is an issue I haven't come across before, and there doesn't appear to be a function for this.
I'm trying to sort the following multi dimensional array by its keys
Array (
[hiphop] => Array (
[0] => 2123
[1] => 5683
[2] => 2345
[3] => 4567
)
[rnb] => Array (
[0] => 2123
[1] => 5683
[2] => 2345
[3] => 4567
)
[dubstep] => Array ( )
[reggae] => Array ( )
[trap] => Array ( )
)
From this arrays values
Array (
[0] => hiphop
[1] => dubstep
[2] => reggae
[3] => trap
[4] => rnb
[5] => rnb
)
Has anyone attempted this before or know a workaround?
An explanation would be great as I'm new to multi dimensional arrays
Many thanks in advance if you can help!
The final output would match the value organsiation from the non multi dimensional array like so
Array (
[hiphop] => Array (
[0] => 2123
[1] => 5683
[2] => 2345
[3] => 4567
)
[dubstep] => Array ( )
[reggae] => Array ( )
[trap] => Array ( )
[rnb] => Array (
[0] => 2123
[1] => 5683
[2] => 2345
[3] => 4567
)
)
The easiest Way would be to "flip" the array definining the sorting - then grab the values matching the new keys in the other array:
$s = array ("hiphop","dubstep","reggae","trap","rnb");
$target = array_flip($s);
foreach($target AS $key => &$value){
$value = $array_containing_unsorted_values[$key];
}
Note: does not work if the same value appears twice in the sorting array - but that never should happen, cause does not make sence for a sorting-definition.
Should be way faster than using array_search 2 times within each sorting comparission.
result:
Array
(
[hiphop] => Array
(
[0] => 2123
[1] => 5683
[2] => 2345
[3] => 4567
)
[dubstep] => Array
(
)
[reggae] => Array
(
)
[trap] => Array
(
)
[rnb] => Array
(
[0] => 2123
[1] => 5683
[2] => 2345
[3] => 4567
)
)
You can use uksort for that, which lets you sort by key, based on a user supplied comparison function. Using that function, you can make a function yourself, so you can hide the complex functionality in an easy one.
For instance, you want a function like ksort, only you want to specify an external array of keys, so such a function could look like this:
bool ksort_ext(&$array, $keys)
For the implementation, you can wrap uksort, like so:
function ksort_ext(&$array, $keys)
{
return uksort($array, function($a, $b) use ($keys) {
// Result of callback is based on the position of $a and $b in $keys
return array_search($a, $keys) - array_search($b, $keys);
});
}
Then, you can call it like you would call other sort functions, only with the external array of keys as a second parameter.
$array1 = array(
'hiphop' => array(1,2,3),
'rnb' => array(1,2,3),
'dubstep' => array(1,2,3),
'reggae' => array(1,2,3),
'trap' => array(1,2,3));
$array2 = array('hiphop', 'dubstep', 'reggae', 'trap', 'rnb');
var_dump(ksort_ext($array1, $array2)); // Should return true
var_dump($array1); // Should display the ordered array,

Need common arrays from two multidimensional arrays

Hi I have below multidimensional arrays -
Array
(
[user_attempts] => 0
[2] => Array
(
[0] => 1
[1] => 4
)
[3] => Array
(
[0] => 32
[1] => 23
)
[4] => Array
(
[0] => asdsa
)
[1] => Array
(
[0] => Earth
)
)
and my second array is like below
Array
(
[1] => Array
(
[0] => Earth
)
[2] => Array
(
[0] => 2
[1] => 3
)
[3] => Array
(
[0] => 32
[1] => 23
)
[4] => Array
(
[0] => asdsa
[1] => asdas
)
)
I need to intersect both multidimensional arrays - so the result would be
Array
(
[1] => Array
(
[0] => Earth
)
[3] => Array
(
[0] => 32
[1] => 23
)
)
Can anyone help me to sort this out.
What I have tried is using array_intersect() but it limits to single array not multidimensional i guess.
PHP comes with a ton of functions already built in, but sometimes you still have to implement things yourself. What you want to do can be easily done by using the existing functions.
The goal is to do the following steps:
Find the keys that exist in both arrays
Loop through the array using these keys
Take the items of both input arrays with each of these keys
Calculate the intersection of those two arrays
Put it into a result array
Here is one way to do this:
function array_intersect_2dim (array $a1, array $a2) {
$keys = array_intersect(array_keys($a1), array_keys($a2));
$return = array();
foreach ($keys as $key) {
$return[$key] = array_intersect($a1[$key], $a2[$key]);
if (sizeof($return[$key]) == 0) {
unset($return[$key]);
}
}
return $return;
}
It works only for two dimensions. If you need more, you have to build a recursive approach, which follows the exact same principle.
To make the easier to compare you can use serialize/unserialize on this one. And then use array_intersect(). Try this example: Sample Output
$array1 = array( 'user_attemps' => 0, 2 => array(1, 4), 3 => array(32, 23), 4 => array('asdsa'), 1 => array('Earth'),);
$array2 = array( 1 => array('Earth'), 2 => array(2, 3), 3 => array(32, 23), 4 => array('asdsa', 'asdas'),);
$result = array_map('unserialize',array_intersect(array_map('serialize', $array1), array_map('serialize', $array2)));
print_r($result);

PHP three dimensional array, reset key if second element different

Let say i have this print_r output, this is dynamic and not same each condition
Array
(
[2] => Array
(
[1] => 24
[2] => 23,25
)
[3] => Array
(
[3] => 27
[4] => 27,26
[5] => 28,27,26
)
)
As you can see, array element [3] starts from [3][4][5], how do it make it start from [1][2]...[n] if the 2nd element is not same.
Ideally what i am looking for is something like
Array
(
[2] => Array
(
[1] => 24
[2] => 23,25
)
[3] => Array
(
[1] => 27
[2] => 27,26
[3] => 28,27,26
)
)
How do i achieve that? Thanks
array_values returns the values of an array with new numeric indices:
foreach($a as $k => $v) {
$a[$k] = array_values($v);
}
Add conditions if you only want to re-index some of your sub-arrays.
Functional approach:
$a = array_map(function($v) {
return array_values($v);
}, $a);

Categories