Group by common array keys - php

$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.

Related

How to simplify this function and make it universal for n-level depth?

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));

Merging multidimensional arrays by matching key-value pairs of subarrays?

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

Filter multidimension array with conditional logic

I have below array,
Array ( [0] => Array ( [location] => X33 [usernumber] => 1 [order] => XX [part_number] => Hi ) [1] => Array ( [location] => X33 [usernumber] => 1 [order] => XX [part_number] => 68730 ) [2] => Array ( [location] => W33 [usernumber] => 2 [order] => YY [part_number] => 68741) [3] => Array ( [location] => W33 [usernumber] => 2 [order] => YY [part_number] => Hello )
I want to filter this array with usernumber = 1, by this it will create 1 array with arrays which have usernumber = 1, similarly it will create for usernumber=2
I had users in DB and will search user in this array,
I tried below code,
$users = $this->admin_model->get_usersforshipment();
foreach ($users as $user) {
$filtered = array_filter($csv_array, function($user)
{ //Below is retrurning as orignal $csv_array, not filtered,
return !empty($user['usernumber']);
});
}
Desired output, when $users['usernumber] == 1
Array ( [0] => Array ( [location] => X33 [usernumber] => 1 [order] => XX [part_number] => Hi ) [1] => Array ( [location] => X33 [usernumber] => 1 [order] => XX [part_number] => 68730 ) )
Desired output, when $users['usernumber] == 2
Array ( [0] => Array ( [location] => W33 [usernumber] => 2 [order] => YY [part_number] => 68741) [1] => Array ( [location] => W33 [usernumber] => 2 [order] => YY [part_number] => Hello )
How can i filter only 2 arrays from Multi Dimension array?
Online Example, Description added after your feedback.
$arr = array(
array ('location' => 'X33',
'usernumber' => 1,
'order' => 'XX',
'part_number' => 'Hi'
),
array ('location' => 'X33',
'usernumber' => 1,
'order' => 'XX',
'part_number' => '68730'
),
array ('location' => 'W33',
'usernumber' => 2,
'order' => 'YY',
'part_number' => '68741'
),
array ('location' => 'W33',
'usernumber' => 2,
'order' => 'YY',
'part_number' => 'Hello'
)
);
$out = array();
$index = $arr[0]['usernumber'];
foreach($arr as $val){
if($index != $val['usernumber'])
$index = $val['usernumber'];
$out[$index][] = $val;
}
echo '<pre>';
print_r($out);
Currently, your array is defined like so:
$array = [
0 => [
'location' => l1
'usernumber' => 1
'order' => 'o1'
],
1 => [
'location' => l2
'usernumber' => 1
'order' => 'o2'
],
2 => [
'location' => l3
'usernumber' => 2
'order' => 'o3'
]
];
A good solution would be to set the usernumber variables as array keys. You could do this while creating the array, or you could alter it after creation. It should look like this:
$array = [
1 => [ // The key is now the usernumber
[
'location' => 'l1'
'order' => 'o1'
],
[
'location' => 'l2'
'order' => 'o2'
]
],
2 => [
[
'location' => 'l3'
'order' => 'o3'
],
]
];
Now you can simple grab the different orders by the usernumber and loop through them:
$orders = $array[1]; // Get all orders from the user with usernumber 1
foreach ($orders as $order) {
print_r($order);
}

Custom sorting array of arrays using two conditions

I have the following array:
$arr = [
[
'user_id' => 1,
'product_id' => 1
],
[
'user_id' => 1,
'product_id' => 2
],
[
'user_id' => 1,
'product_id' => 3
],
[
'user_id' => 2,
'product_id' => 1
],
[
'user_id' => 2,
'product_id' => 2
],
[
'user_id' => 3,
'product_id' => 1
]
];
And I want to sort it so it looks like this:
$arr = [
[
'user_id' => 1,
'product_id' => 1
],
[
'user_id' => 2,
'product_id' => 1
],
[
'user_id' => 3,
'product_id' => 1
],
[
'user_id' => 1,
'product_id' => 2
],
[
'user_id' => 2,
'product_id' => 2
],
[
'user_id' => 1,
'product_id' => 3
]
];
So basically I need to order by product_id and user_id in such a way that it selects the lower number product_id from each user before proceeding to the next.
I tried to use usort but I couldn't get it to work.
usort($campaigns, function($a, $b){
if($a['product_id'] == $b['product_id']){
return 0;
}
if($a['product_id'] < $b['product_id']){
if($a['user_id'] == $b['user_id']){
return 1;
}
if($a['user_id'] < $a['user_id']){
return 0;
}
return -1;
}else{
if($a['user_id'] == $a['user_id']){
return -1;
}
if($a['user_id'] < $a['user_id']){
return 0;
}
return 1;
}
});
I also tried array_multisort but all I could get it to do is to order using the same order that I already retrieve from the database.
Assumption is your values is integers:
usort($campaigns, function($a, $b){
if($a['product_id'] == $b['product_id']){
return $a['user_id'] - $b['user_id'];
} else {
return $a['product_id'] - $b['product_id'];
}
});
Also you can use database ordering with ORDER BY product_id, user_id clause.
Solution using array_multisort function with "array of columns"(few sorting dimensions):
$userIds = $productIds = [];
foreach ($arr as $k => $v) {
$userIds[$k] = $v['user_id'];
$productIds[$k] = $v['product_id'];
}
array_multisort($productIds, SORT_ASC, $userIds, SORT_ASC, $arr);
print_r($arr);
The output:
Array
(
[0] => Array
(
[user_id] => 1
[product_id] => 1
)
[1] => Array
(
[user_id] => 2
[product_id] => 1
)
[2] => Array
(
[user_id] => 3
[product_id] => 1
)
[3] => Array
(
[user_id] => 1
[product_id] => 2
)
[4] => Array
(
[user_id] => 2
[product_id] => 2
)
[5] => Array
(
[user_id] => 1
[product_id] => 3
)
)
$arrTags = [
[
'user_id' => 1,
'product_id' => 1
],
[
'user_id' => 1,
'product_id' => 2
],
[
'user_id' => 1,
'product_id' => 3
],
[
'user_id' => 2,
'product_id' => 1
],
[
'user_id' => 2,
'product_id' => 2
],
[
'user_id' => 3,
'product_id' => 1
]
];
foreach($arrTags as $key => $row){
$userArray[$key] = $row['user_id'];
$productArray[$key] = $row['product_id'];
}
array_multisort($productArray, SORT_ASC, $userArray, SORT_ASC, $arrTags);
print_r($arrTags);
Output
Array
(
[0] => Array
(
[user_id] => 1
[product_id] => 1
)
[1] => Array
(
[user_id] => 2
[product_id] => 1
)
[2] => Array
(
[user_id] => 3
[product_id] => 1
)
[3] => Array
(
[user_id] => 1
[product_id] => 2
)
[4] => Array
(
[user_id] => 2
[product_id] => 2
)
[5] => Array
(
[user_id] => 1
[product_id] => 3
)
)
You can also check in online editor. Click Here

Compare value in three array and get specific value in php

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
);

Categories