I am comparing three value in an array and i am getting all value.
How can i output specific value or value that i only want to output
Because i want to output value that i only nedeed.
I have this code:
<?php
$participants = [
[ 'calleridnum' => 1,
'callee' => 'yay'
],
[ 'calleridnum' => 2,
'callee' => 'yay'
],
[ 'calleridnum' => 3,
'callee' => 'yay'
]
];
$conferance_participants = [
[ 'uid' => 1,
'caller' => 'yay2',
'dit' => 'deze'
],
[ 'uid' => 2,
'caller' => 'test',
'dit' => 'wew'
]
];
$contacts = [
[ 'name' => 1,
'test' => 'yay2',
'limit' => 1
],
[ 'name' => 2,
'test' => 'yay2',
'limit' => 1
]
];
foreach ($participants as $participant=>$p) {
foreach ($conferance_participants as $conferance_participant=>$cp) {
foreach ($contacts as $contact=>$cs) {
if (($p['calleridnum'] == $cp['uid']) && ($cp['uid'] == $cs['name'])){
$conferance_participants[$conferance_participant] = array_merge(
$participants[$participant],
$conferance_participants[$conferance_participant],
$contacts[$contact]
);
}
}
}
}
echo "<pre>";
print_r($conferance_participants);
echo "</pre>";
?>
and my output is:
Array
(
[0] => Array
(
[calleridnum] => 1
[callee] => yay
[uid] => 1
[caller] => yay2
[dit] => deze
[name] => 1
[test] => yay2
[limit] => 1
)
[1] => Array
(
[calleridnum] => 2
[callee] => yay
[uid] => 2
[caller] => test
[dit] => wew
[name] => 2
[test] => yay2
[limit] => 1
)
)
I want ot minimize my output.
I want to remove name test from the $contacts array
I also want to remove caller dit from the $conferance_participants array
so that my output will be :
Array
(
[0] => Array
(
[calleridnum] => 1
[callee] => yay
[uid] => 1
[limit] => 1
)
[1] => Array
(
[calleridnum] => 2
[callee] => yay
[uid] => 2
[limit] => 1
)
)
Your code is hard to understand,
Number of times your foreach will execute,
count($participants) * count($conferance_participants) * count($contacts);
Number of times this code's foreach will execute will be equal or less than your codes, because it will stop as soon as the match found.
Also i have created a new function, for searching in another arrays, so it will make the next person working on this code less bang his head on the desk.
Passes $conferance_participants variable's value as reference, note the & in foreach declaration so no need to worry about keys of the array.
foreach($conferance_participants as &$record) {
# find keys of corresponding array matches
$key_in_participants = _custom_search($record['uid'], $participants, 'calleridnum');
$key_in_contacts = _custom_search($record['uid'], $contacts, 'name');
# unset unwanted things
unset($record['caller'], $record['dit']);
# activate this code if you want to make false for unmatched records
/* ***********************************************************************
if($key_in_participants === false || $key_in_contacts === false) {
$record['calleridnum'] = $record['callee'] = $record['limit'] = false;
continue;
}
*********************************************************************** */
# setting required things
$record['calleridnum'] = $participants[$key_in_participants]['calleridnum'];
$record['callee'] = $participants[$key_in_participants]['callee'];
$record['limit'] = $contacts[$key_in_contacts]['limit'];
}
function _custom_search($id, $array, $key_to_search) {
foreach ($array as $key => $val) if($val[$key_to_search] === $id) return $key;
return false;
}
This will make $conferance_participants exactly as you want.
You can just unset the array keys before you merge the arrays. Then set the 'name' key again for $contacts array which is needed for the loops above.
Here is the modified code sample:
<?php
$participants = [
[ 'calleridnum' => 1,
'callee' => 'yay'
],
[ 'calleridnum' => 2,
'callee' => 'yay'
],
[ 'calleridnum' => 3,
'callee' => 'yay'
]
];
$conferance_participants = [
[ 'uid' => 1,
'caller' => 'yay2',
'dit' => 'deze'
],
[ 'uid' => 2,
'caller' => 'test',
'dit' => 'wew'
]
];
$contacts = [
[ 'name' => 1,
'test' => 'yay2',
'limit' => 1
],
[ 'name' => 2,
'test' => 'yay2',
'limit' => 1
]
];
foreach ($participants as $participant=>$p) {
foreach ($conferance_participants as $conferance_participant=>$cp) {
foreach ($contacts as $contact=>$cs) {
if (($p['calleridnum'] == $cp['uid']) && ($cp['uid'] == $cs['name'])){
unset($contacts[$contact]['name'], $contacts[$contact]['test']);
unset($conferance_participants[$conferance_participant]['caller'], $conferance_participants[$conferance_participant]['dit']);
$conferance_participants[$conferance_participant] = array_merge(
$participants[$participant],
$conferance_participants[$conferance_participant],
$contacts[$contact]
);
$contacts[$contact]['name'] = $cs['name'];
}
}
}
}
echo "<pre>";
print_r($conferance_participants);
echo "</pre>";
The output you should get:
Array
(
[0] => Array
(
[calleridnum] => 1
[callee] => yay
[uid] => 1
[limit] => 1
)
[1] => Array
(
[calleridnum] => 2
[callee] => yay
[uid] => 2
[limit] => 1
)
)
I hope that answers your question. Thanks.
After merging, you may filter only certain keys you want to be present in final result using array_intersect_key().
$keys = array_flip(['calleridnum', 'callee', 'uid', 'limit']);
$conferance_participants[$conferance_participant] =
array_intersect_key(
array_merge(
$participants[$participant],
$conferance_participants[$conferance_participant],
$contacts[$contact]
),
$keys
);
Related
I seem to struggle with (for me) complex recursive functions. Could anyone point me in the right direction so that I can simplify this messy and repetitive code? Also, it's meant to work for n-level deep.
$hasProducts = array();
function filterOutEmpty($levelZero) {
global $hasProducts;
foreach ($levelZero as $levelZeroK => $levelZeroV) {
if (empty($levelZeroV['products']) && empty($levelZeroV['families'])) continue;
if (!empty($levelZeroV['products'])) {
$hasProducts[$levelZeroK] = $levelZeroV;
}
if (!empty($levelZeroV['families'])) {
foreach ($levelZeroV['families'] as $levelOneK => $levelOneV) {
if (empty($levelOneV['products']) && empty($levelOneV['families'])) continue;
if (!empty($levelOneV['products'])) {
$hasProducts[$levelZeroK]['families'][$levelOneK] = $levelOneV;
}
if (!empty($levelOneV['families'])) {
foreach ($levelOneV['families'] as $levelTwoK => $levelTwoV) {
if (empty($levelTwoV['products']) && empty($levelTwoV['families'])) continue;
if (!empty($levelTwoV['products'])) {
$hasProducts[$levelZeroK]['families'][$levelOneK]['families'][$levelTwoK] = $levelTwoV;
}
}
}
}
}
}
}
Sample input could be as follows:
$districts = [
1 => [
'id' => 1,
'families' => [
0 => [
'id' => 2
],
1 => [
'id' => 3,
'families' => [
0 => [
'id' => 2,
'products' => [
1 => 'Arnold'
],
],
1 => [
'id' => 2,
'products' => [],
],
]
],
]
],
2 => [
'id' => 1,
'families' => [
0 => [
'id' => 2,
'products' => [
1 => 'John Doe'
],
],
1 => [
'id' => 3,
'products' => [],
],
]
],
3 => [
'id' => 1,
'products' => [
1 => 'Hi',
2 => 'Hello',
]
],
4 => [
'id' => 1,
'families' => [
0 => [
'id' => 2
],
1 => [
'id' => 3
],
]
],
];
The desired output:
(
[1] => Array
(
[families] => Array
(
[1] => Array
(
[families] => Array
(
[0] => Array
(
[id] => 2
[products] => Array
(
[1] => Arnold
)
)
)
)
)
)
[2] => Array
(
[families] => Array
(
[0] => Array
(
[id] => 2
[products] => Array
(
[1] => John Doe
)
)
)
)
[3] => Array
(
[id] => 1
[products] => Array
(
[1] => Hi
[2] => Hello
)
)
)
Please, keep in mind, that the array can be nested x-levels deep, this is just as an example. With each level I would need to add another if check (!empty($level{SOME_LEVEL}V['families'])) { ... the code again for a particular level... }
This code uses a recursive function to parse each level, so the number of levels doesn't matter. Each time it enters the routine it gets passed in the current level and will return the representation of that level in the new format ( I think ).
The one part is that after each recursive call, it checks if the return value is empty and only adds it in if it contains something...
function filterOutEmpty($levelZero) {
$hasProducts = [];
foreach ($levelZero as $levelZeroK => $levelZeroV) {
if (!empty($levelZeroV['products'])) {
$hasProducts[$levelZeroK] = $levelZeroV;
}
else if ( is_array($levelZeroV)) {
$new = filterOutEmpty($levelZeroV);
if ( !empty($new) ) {
$hasProducts[$levelZeroK] = $new;
}
}
if (!empty($levelZeroV['families'])) {
$new = filterOutEmpty($levelZeroV['families']);
if ( !empty($new) ) {
$hasProducts[$levelZeroK]['families'] = $new;
}
}
}
return $hasProducts;
}
print_r(filterOutEmpty($districts));
I have an associative array key/values indicating a group. I'd like to shuffle the array so that the groups are in a random order but so that the items in the groups are shuffled only within their group. In other words, I want to take something like this:
[
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Spike",
"group" => 3
]
]
And return something a bit more like this:
[
[
"name" => "Spike",
"group" => 3
]
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
]
I realise this is probably possible with two or three sorts, but it would be great if this could be done with a single usort.
Basically, my solution shuffles the input array, temporarily restructures the input array to gather subarrays with the same group value, then returns the data to its original structure.
Code: (Demo)
shuffle($data); // randomize all subarrays
foreach ($data as $set) {
$grouped[$set['group']][] = $set; // merge subarrays on group value
}
$output = [];
foreach($grouped as $group) {
array_push($output, ...$group); // return to original array structure
}
var_export($output);
*Note that ... (splat operator) allows array_push() to store all subarrays (within each group) individually to generate the original structure.
Possible Output:
array (
0 =>
array (
'name' => 'Xander',
'group' => 2,
),
1 =>
array (
'name' => 'Giles',
'group' => 2,
),
2 =>
array (
'name' => 'Willow',
'group' => 1,
),
3 =>
array (
'name' => 'Buffy',
'group' => 1,
),
4 =>
array (
'name' => 'Spike',
'group' => 3,
),
5 =>
array (
'name' => 'Tara',
'group' => 3,
),
6 =>
array (
'name' => 'Angel',
'group' => 3,
),
)
Try...
$groups = [];
foreach (array_unique(array_column($myar, 'group')) as $k) $groups[$k] = rand();
foreach (array_keys($myar) as $k) $myar[$k]['rnd'] = rand();
usort($myar, function($a, $b) use ($groups) {
if ($gdif = $groups[$b['group']] - $groups[$a['group']]) return $gdif;
return $b['rnd'] - $a['rnd'];
});
foreach (array_keys($myar) as $k) unset($myar[$k]['rnd']);
print_r($myar);
Run with your data, this is one result...
Array
(
[0] => Array
(
[name] => Buffy
[group] => 1
)
[1] => Array
(
[name] => Willow
[group] => 1
)
[2] => Array
(
[name] => Angel
[group] => 3
)
[3] => Array
(
[name] => Tara
[group] => 3
)
[4] => Array
(
[name] => Spike
[group] => 3
)
[5] => Array
(
[name] => Giles
[group] => 2
)
[6] => Array
(
[name] => Xander
[group] => 2
)
)
I need to sort an multi dimensional array which looks like this down below (usort already applied).
I need to move '10000_M3' to the first key if an identifier '_M' was found (as natural sorting), but the order from 'first' sort should not be touched.
Extra: (Optional) If i have a description like '10000_0', it should be still in index 0
If the usort can be done in 1 step would be great
I take any solution (usort, foreach, ..)!!!
usort($anArray, function ($a, $b) {
return strnatcmp($a['description'], $b['description']);
});
$anArray = [
// ? => [
// 'description' => '10000_0'
// ]
0 => [
'description' => '10000_D2'
],
1 => [
'description' => '10000_D3'
],
2 => [
'description' => '10000_M3'
],
3 => [
'description' => '10000_M4'
]
]
Result (Natural -> at first position = '_0' -> $ident = '_M' after '_0' if its exists):
$result = [
0 => [
'description' => '10000_0'
]
1 => [
'description' => '10000_M3'
],
2 => [
'description' => '10000_M4'
]
3 => [
'description' => '10000_D2'
],
4 => [
'description' => '10000_D3'
],
]
You can modify your sort function to check for the special cases individually then fall back on a regular sorting method.
<?php
$inputArray = [
0 => [
'description' => '10000_D2'
],
1 => [
'description' => '10000_D3'
],
2 => [
'description' => '10000_M3'
],
3 => [
'description' => '10000_M4'
],
4 => [
'description' => '10000_0'
]
];
usort($inputArray, function ($a, $b) {
// _0 first then _M* then alphabetic
//assume only 1 value will be _0?
if (preg_match('/_0$/', $a['description']) === 1){
//"a" ends in _0
return -1;
}
if (preg_match('/_0$/', $b['description']) === 1){
//"b" ends in _0
return 1;
}
if (
preg_match('/_M\d*$/', $a['description']) === 1
&& preg_match('/_M\d*$/', $b['description']) === 1
){
//both have "M" so sort them normally
return strnatcmp($a['description'], $b['description']);
}
if (preg_match('/_M\d*$/', $a['description']) === 1){
//only "a" has _M
return -1;
}
if (preg_match('/_M\d*$/', $b['description']) === 1){
//only "b" has _M
return 1;
}
//neither side has _M or _0 so normal sorting
return strnatcmp($a['description'], $b['description']);
});
echo print_r($inputArray, true);
?>
Output:
Array
(
[0] => Array
(
[description] => 10000_0
)
[1] => Array
(
[description] => 10000_M3
)
[2] => Array
(
[description] => 10000_M4
)
[3] => Array
(
[description] => 10000_D2
)
[4] => Array
(
[description] => 10000_D3
)
)
I'm assuming you will only have a single _0 value. If you could have multiple _0 values then you need to modify the above code to behave like the 3 _M "if" statements.
You can try this :
$anArray = [
0 => [
'description' => '10000_D2'
],
1 => [
'description' => '10000_D3'
],
2 => [
'description' => '10000_M3'
],
3 => [
'description' => '10000_M4'
]
, 4 => [
'description' => '10000_0'
]
, 5 => [
'description' => '10000_15'
]
, 6 => [
'description' => '10000_789'
]
];
usort($anArray, function ($a, $b) {
$tmpa=explode('_',$a['description']);
$tmpb=explode('_',$b['description']);
if(ctype_digit($tmpa[1])&&!ctype_digit($tmpb[1]))
return -1;
if(!ctype_digit($tmpa[1])&&ctype_digit($tmpb[1]))
return 1;
if($tmpa[1][0]==='M'&&$tmpb[1][0]!=='M')
return -1;
if($tmpa[1][0]!=='M'&&$tmpb[1][0]==='M')
return 1;
return strnatcmp($a['description'], $b['description']);
});
print_r($anArray);
and the output is:
Array
(
[0] => Array
(
[description] => 10000_0
)
[1] => Array
(
[description] => 10000_15
)
[2] => Array
(
[description] => 10000_789
)
[3] => Array
(
[description] => 10000_M3
)
[4] => Array
(
[description] => 10000_M4
)
[5] => Array
(
[description] => 10000_D2
)
[6] => Array
(
[description] => 10000_D3
)
)
$sortMod = [
[
'group_id' => 1,
'group_name'=>'Home',
'module_id' => 1,
'mod_name' => 'Home',
'mod_link' => '/home',
'var_name' => 'home'
], [
'group_id'=> 2,
'module_id' => 2,
'mod_name' => 'Numbers',
'mod_link' => '/number_mapping',
'var_name' => 'numbermap'
], [
'group_id'=> 2,
'module_id' => 70,
'mod_name' => 'DR Plan',
'mod_link' => '/dr_plan',
'var_name' => 'dr_plan'
], [
'group_id'=> 3,
'module_id' => 8,
'mod_name' => 'Reporting',
'mod_link' => '/reporting',
'var_name' => 'reporting'
], [
'group_id'=> 3,
'module_id' => 80,
'mod_name' => 'Scheduler',
'mod_link' => '/scheduler',
'var_name' => 'scheduler'
]
];
I want to group the result by group_id;
$sortMod = [
[
'group_id' => 1,
'group_name'=>'Home',
'module_id' => 1,
'mod_name' => 'Home',
'mod_link' => '/home',
'var_name' => 'home'
], [
'group_id'=> 2,
[
'module_id' => 2,
'mod_name' => 'Numbers',
'mod_link' => '/number_mapping',
'var_name' => 'numbermap'
], [
'module_id' => 70,
'mod_name' => 'DR Plan',
'mod_link' => '/dr_plan',
'var_name' => 'dr_plan'
]
], [
'group_id'=> 3,
[
'module_id' => 8,
'mod_name' => 'Reporting',
'mod_link' => '/reporting',
'var_name' => 'reporting'
], [
'module_id' => 80,
'mod_name' => 'Scheduler',
'mod_link' => '/scheduler',
'var_name' => 'scheduler'
]
]
];
Currently I have this:
$groups = [];
$modules = array();
I am iterating over the array $sortMod and group it by group_id where multiple module_id appears i.e group_id 2 and 3 has multiple modules in them. So the result will look what is stated above. Although I know I can have a flag variable $groupExist set to false by default and when the group is pushed into the $groups array, the value is set to false. Then have an if statement check if the value is true, then push just the module values :
foreach($sortMod as $val) {
if(!array_key_exists($val['group_id'],$groups)){
$groups[$val['group_id']] = [];
}
$groups[$val['group_id']][] = $val;
}
echo '<pre>';
print_r($groups);
echo '<pre>';
You can use array_reduce to group the array. If you don't want to make a multidimensional array if the group has only one element, you can use array_map
$sortMod = .. //Your array here.
$grouped = array_reduce($sortMod, function($c, $v){
$c[ $v['group_id'] ][] = $v;
return $c;
}, array());
$result = array_map(function ($n) {
if ( count($n) === 1 ) return $n[0]; //Since the group has one element. Return the element 0.
$newN = array(); //Contruct the new format for 2 or more elements.
$newN['group_id'] = $n[0]['group_id']; //Add the group_id
foreach($n as $value) //Loop thru the array, remove the group_id and push.
{
unset($value['group_id']);
$newN[] = $value;
}
return $newN;
}, $grouped );
echo "<pre>";
print_r( $result );
echo "</pre>";
This will result to:
Array
(
[1] => Array
(
[group_id] => 1
[group_name] => Home
[module_id] => 1
[mod_name] => Home
[mod_link] => /home
[var_name] => home
)
[2] => Array
(
[group_id] => 2
[0] => Array
(
[module_id] => 2
[mod_name] => Numbers
[mod_link] => /number_mapping
[var_name] => numbermap
)
[1] => Array
(
[module_id] => 70
[mod_name] => DR Plan
[mod_link] => /dr_plan
[var_name] => dr_plan
)
)
[3] => Array
(
[group_id] => 3
[0] => Array
(
[module_id] => 8
[mod_name] => Reporting
[mod_link] => /reporting
[var_name] => reporting
)
[1] => Array
(
[module_id] => 80
[mod_name] => Scheduler
[mod_link] => /scheduler
[var_name] => scheduler
)
)
)
Adding some little modifications to your code would make a something like that
$group = [];
foreach ($sortMod as $val){
$current_id = $val['group_id'];
unset($val['group_id']);
if (!array_key_exists($current_id ,$group)){
$group[$current_id] = array();
}
$group[$current_id][] = $val;
}
echo '<pre>';
print_r($groups);
echo '<pre>';
You could add your $val into the group using the group_id. If you find this key, you can create the group_id key. If you find it again, and it's an array, append to it.
$groups = [];
foreach($sortMod as $val)
{
$group_id = $val['group_id'];
if (!isset($groups[$group_id])) { // First case
$groups[$group_id] = $val ;
continue;
}
// regroup if 'group_id' is not an array
if (!is_array($groups[$group_id]['group_id']))
{
unset($groups[$group_id]['group_id']);
$groups[$group_id] = ['group_id' => $group_id, $groups[$group_id]] ;
}
// append the new group
unset($val['group_id']);
$groups[$group_id][] = $val ;
}
// optionnal (to remove group_id keys)
$groups = array_values($groups);
print_r($groups);
Outputs:
Array
(
[0] => Array
(
[group_id] => 1
[group_name] => Home
[module_id] => 1
[mod_name] => Home
[mod_link] => /home
[var_name] => home
)
[1] => Array
(
[group_id] => 2
[0] => Array
(
[module_id] => 2
[mod_name] => Numbers
[mod_link] => /number_mapping
[var_name] => numbermap
)
[1] => Array
(
[module_id] => 70
[mod_name] => DR Plan
[mod_link] => /dr_plan
[var_name] => dr_plan
)
)
[2] => Array
(
[group_id] => 3
[0] => Array
(
[module_id] => 8
[mod_name] => Reporting
[mod_link] => /reporting
[var_name] => reporting
)
[1] => Array
(
[module_id] => 80
[mod_name] => Scheduler
[mod_link] => /scheduler
[var_name] => scheduler
)
)
)
You could use a generic custom function like so:
function array_group_by($a, $i, $rem = true){
foreach($a as $v){
$k = $v[$i];
if($rem){
unset($v[$i]);
}
$t[$k][] = $v;
}
return $t;
}
echo '<pre>';
print_r(array_group_by($sortMod, 'group_id'));
echo '<pre>';
And here is the output.
A group id is supposed to be unique anyways, while this output is not what you specifically wanted it makes a more usable array to loop over.
The first key is the group_id. The following arrays that are in the group array contains are the "modules".
Optionally, you can use array_group_by($sortMod, 'group_id', false); to keep the group_id within that array.
Now when looping over it:
foreach(array_group_by($sortMod, 'group_id') as $groupid => $modules){
echo "$groupid is the group_id and contains " . count($modules) . " modules";
foreach($modules as $module){
echo "Hi from " . $module['module_id'];
}
}
In my opinion, short and reusable code is the way to go.
The task is to merge ("inexpensively") two arrays, which have matching key-value pairs of subarrays. E.g.:
Array 1:
Array
(
[0] => Array
(
[count] => 1
[da_table] => article
[da_class] => classes\elements\tables\Article
[da_page_class] => Page_Article
)
[1] => Array
(
[count] => 2
[da_table] => client_contract_specification_price
[da_class] => classes\elements\tables\ClientContractSpecificationPrice
[da_page_class] => Page_ClientContractSpecification
)
[2] => Array
(
[count] => 2
[da_table] => supplier
[da_class] => classes\elements\tables\Supplier
[da_page_class] => Page_Supplier
)
)
Array 2:
Array
(
[0] => Array
(
[name] => Articles
[name_short] =>
[da_page_class] => Page_Article
)
[1] => Array
(
[name] => Client contract specifications
[name_short] => cc_specifications
[da_page_class] => Page_ClientContractSpecification
)
[2] => Array
(
[name] => Suppliers
[name_short] =>
[da_page_class] => Page_Supplier
)
)
How to merge the two above arrays by a matching [da_page_class] => ... pairs, so the resulting array will contain both key-values of the first and the second array, i.e.:
...
[0] => Array
(
[count] => 1
[da_table] => article
[da_class] => classes\elements\tables\Article
[da_page_class] => Page_Article
[name] => Articles
[name_short] =>
)
...
Additional requirements:
Subarrays may come in random order. Also, there can be "orphans", which contain values of ['da_page_class'], but have no match in another array. These should be ignored.
Well, you simply iterate over the array elements and combine them:
<?php
$data1 = [
[
'count' => 1,
'da_table' => 'article',
'da_class' => 'classes\elements\tables\Article',
'da_page_class' => 'Page_Article'
],
[
'count' => 2,
'da_table' => 'client_contract_specification_price',
'da_class' => 'classes\elements\tables\ClientContractSpecificationPrice',
'da_page_class' => 'Page_ClientContractSpecification'
],
[
'count' => 2,
'da_table' => 'supplier',
'da_class' => 'classes\elements\tables\Supplier',
'da_page_class' => 'Page_Supplier'
]
];
$data2 = [
[
'name' => 'Articles',
'name_short' => null,
'da_page_class' => 'Page_Article'
],
[
'name' => 'Client contract specifications',
'name_short' => 'cc_specifications',
'da_page_class' => 'Page_ClientContractSpecification'
],
[
'name' => 'Suppliers',
'name_short' => null,
'da_page_class' => 'Page_Supplier'
]
];
$output = [];
for ($i=0; $i<count($data1); $i++) {
$output[$i] = array_merge($data1[$i], $data2[$i]);
}
print_r($output);
The output obviously is:
Array
(
[0] => Array
(
[count] => 1
[da_table] => article
[da_class] => classes\elements\tables\Article
[da_page_class] => Page_Article
[name] => Articles
[name_short] =>
)
[1] => Array
(
[count] => 2
[da_table] => client_contract_specification_price
[da_class] => classes\elements\tables\ClientContractSpecificationPrice
[da_page_class] => Page_ClientContractSpecification
[name] => Client contract specifications
[name_short] => cc_specifications
)
[2] => Array
(
[count] => 2
[da_table] => supplier
[da_class] => classes\elements\tables\Supplier
[da_page_class] => Page_Supplier
[name] => Suppliers
[name_short] =>
)
)
Alternatively you could also merge the contents of the elements of the second array into the corresponding elements of the first array. That reduces the memory footprint for large data sets.
Considering the additional requirement you specified in your comment I changed the merge strategy to allow for arbitrary orders of the two sets:
<?php
$data1 = [
[
'count' => 1,
'da_table' => 'article',
'da_class' => 'classes\elements\tables\Article',
'da_page_class' => 'Page_Article'
],
[
'count' => 2,
'da_table' => 'client_contract_specification_price',
'da_class' => 'classes\elements\tables\ClientContractSpecificationPrice',
'da_page_class' => 'Page_ClientContractSpecification'
],
[
'count' => 2,
'da_table' => 'supplier',
'da_class' => 'classes\elements\tables\Supplier',
'da_page_class' => 'Page_Supplier'
]
];
$data2 = [
[
'name' => 'Articles',
'name_short' => null,
'da_page_class' => 'Page_Article'
],
[
'name' => 'Client contract specifications',
'name_short' => 'cc_specifications',
'da_page_class' => 'Page_ClientContractSpecification'
],
[
'name' => 'Suppliers',
'name_short' => null,
'da_page_class' => 'Page_Supplier'
]
];
$output = [];
array_walk($data1, function($entry, $key) use (&$output, $data2) {
$output[$key] = $entry;
foreach($data2 as $cand) {
if ($entry['da_page_class'] == $cand['da_page_class']) {
$output[$key] = array_merge($output[$key], $cand);
}
}
});
print_r($output);
The resulting output obviously is identical to above.
O(m*n) solution:
$result = array();
foreach ($array1 as $value1) {
// do not handle elements without pageclass
if (!array_key_exists('da_page_class', $value1) || !$value1['da_page_class']) {
continue;
}
foreach ($array2 as $value2) {
if (!array_key_exists('da_page_class', $value2) || !$value2['da_page_class']) {
continue;
}
if ($value1['da_page_class'] == $value2['da_page_class']) {
array_push($result, $value1 + $value2)
break;
}
}
}
print_r($result);
O(m+n) solution:
$result = array();
foreach ($array1 as $value) {
// do not handle elements without pageclass
if (!array_key_exists('da_page_class', $value) || !$value['da_page_class']) {
continue;
}
$result[$value['da_page_class']] = $value;
}
foreach ($array2 as $value) {
if (
// do not handle elements without pageclass
!array_key_exists('da_page_class', $value) || !$value['da_page_class'] ||
// do not handle elements that do not exist in array 1
!array_key_exists($value['da_page_class'], $result)
) {
continue;
}
// merge values of this pageclass
$result[$value['da_page_class']] = array_merge($result[$value['da_page_class']], $value);
}
print_r($result);
EDIT: added O(m+n) solution