Merge arrays of associative arrays by shared column values [duplicate] - php

This question already has answers here:
Merge two 2d arrays by shared column value
(6 answers)
Closed last month.
I want to merge two arrays based on a common column value. Here are my 2 arrays:
$array1 = [
[
"total_process_per_category" => "6",
"category_id" => "1"
],
[
"total_process_per_category" => "2",
"category_id" => "2"
]
];
$array2 = [
[
"total_pinned_per_category" => "16",
"category_id" => "1"
],
[
"total_pinned_per_category" => "4",
"category_id" => "2"
]
];
I want to merge these arrays to get:
array (
0 =>
array (
'total_process_per_category' => '6',
'total_pinned_per_category' => '16',
'category_id' => '1',
),
1 =>
array (
'total_process_per_category' => '2',
'total_pinned_per_category' => '4',
'category_id' => '2',
),
)
As you can see, the two arrays have the same key ['category_id'] and same value as well.
I want to make a result where ['total_process_per_category'] and ['total_pinned_per_category'] are placed together on the same array based on their ['category_id'] value.
I got this using a nested foreach, but it looks so ugly. Please show me a better way.

you can try array_reduce:
$someVariable = 'someValue';
$result = array_reduce(array_merge($array1, $array2), function ($carry, $item) use ($someVariable) {
if (isset($carry[$item['category_id']])) {
$carry[$item['category_id']] = array_merge($carry[$item['category_id']], $item);
} else {
$carry[$item['category_id']] = $item;
}
return $carry;
}, array());
var_dump($result);

This can be done without an "ugly nested foreach". Merge the two arrays before iterating, the group by the category_id values. After the loop, clear away the temporary first-level keys with array_values().
Code: (Demo) (array_reduce() version)
$result = [];
foreach (array_merge($array1, $array2) as $row) {
$result[$row['category_id']] = ($result[$row['category_id']] ?? []) + $row;
}
var_export(array_values($result));
Output:
array (
0 =>
array (
'total_process_per_category' => '6',
'category_id' => '1',
'total_pinned_per_category' => '16',
),
1 =>
array (
'total_process_per_category' => '2',
'category_id' => '2',
'total_pinned_per_category' => '4',
),
)

Do you want something like:
foreach ( $array1 as $index => $value ) {
$mergeArray[] = [ $value, $array2[$index]];
}

Related

Loop multidimensional line by line

I'm trying to loop through this array to output side by side for every iteration.
$cars = [
'BMW' => [
'Year' => '2020',
'Body' => 'Sedan',
'Mileage' => '100'
],
'Ford' => [
'Year' => '2019',
'Body' => 'SUV',
'Mileage' => '500'
]
];
$count = count(reset($cars));
for($i=0; $i<$count; $i++) {
foreach($cars as $key => $value) {
echo $cars[$key][$i]. '<br>';
}
}
My expected result for every iteration.
2020,2019
Sedan,SUV
100,500
I have searched through some links, but none is specific to a multidimensional array.
Two arrays in foreach loop
How can I loop through two arrays at once?
The other question you point to is about having separate arrays of data, which you could sort of emulate by splitting the main array into parts.
This solution assumes that all of the keys for the values you want are in the first item (as in your example, they all have the 3 values) and loops over the first array element and uses array_column() to extract all of the values from all of the main array elements for that key. Then implode() these values to put them as a CSV list...
foreach ( $cars[array_keys($cars)[0]] as $key => $value) {
echo implode(",", array_column($cars, $key)).PHP_EOL;
}
which with your test data gives...
2020,2019
Sedan,SUV
100,500
You can simply do it by storing your desired array values in another array and then implode them or make them work by your need. Take a look at the following code..
$cars = [
'BMW' => [
'Year' => '2020',
'Body' => 'Sedan',
'Mileage' => '100'
],
'Ford' => [
'Year' => '2019',
'Body' => 'SUV',
'Mileage' => '500'
],
];
$year = [];
$body = [];
$milage = [];
foreach( $cars as $key => $car ){
if( $car['Year'] ){
$year[] = $car['Year'];
}
if( $car['Body'] ){
$body[] = $car['Body'];
}
if( $car['Mileage'] ){
$milage[] = $car['Mileage'];
}
}
var_dump(implode( ',', $year));
var_dump(implode( ',', $body));
var_dump(implode( ',', $milage));
will give you output:
string(9) "2020,2019" string(9) "Sedan,SUV" string(7) "100,500"

Filter 2D array using another 2D array where differently keyed column values intersect

I have an array like this:
$array1 = [
[
'Firepack_sn' => '20012205',
'Installation_Date' => '',
'Type' => 'EH',
'Capacity_m3h' => '81',
'Pressure_bar' => '3,4',
'Rpm' => '2930',
'Power_kw' => '72',
],
[
'Firepack_sn' => '20023901',
'Installation_Date' => '',
'Type' => 'DH',
'Capacity_m3h' => '195',
'Pressure_bar' => '4,2',
'Rpm' => '2000',
'Power_kw' => '72',
],
];
And an array2 like this:
$array2 = [
[
'user_id' => '40009',
'firepack_id' => '20012205',
'activated' => '1',
],
[
'user_id' => '40009',
'firepack_id' => '21020393',
'activated' => '0',
],
];
Now I want to filter the first array, so I only get the rows with a Firepack_sn value that exists in array2 as firepack_id.
Desired output:
[
{
"Firepack_sn":"20012205",
"Installation_Date":"",
"Type":"EH","Standard":"VAS",
"Capacity_m3h":"81",
"Pressure_bar":"3,4",
"Rpm":"2930",
"Power_kw":"72"
}
]
How can I achieve this?
Here is a way to do it :
First, you need to extract the firepack_id you need to look for, then you need to loop through $arr1 and check if Firepack_sn is the same than than one of the firepack_id you extracted before, if yes, then you add it to an array.
$arr1 = json_decode('[{"Firepack_sn":"20012205","Installation_Date":"","Type":"EH","Standard":"VAS","Capacity_m3h":"81","Pressure_bar":"3,4","Rpm":"2930","Power_kw":"72","Pump_Type":"KSB KFP50-200","Motor_Type":"DOOSAN PU066 VAS/CEA","Controller_Type":"WB882-E10 VAS","Pump_sn":"085259","Motor_sn":"EARPA209635","Controller_sn":"","Servicelevel":"","Cust_id":"0","Cust_branche":"","Cust_name":"","Cust_address1":"","Cust_zipcode":"","Cust_city":"","Cust_country":"","Cust_Phone":"","Cust_coachlevel":"","Site_Name":"E-set","Site_address1":"","Site_address2":"","Site_address3":"","Site_zipcode":"","Site_city":"","Site_country":"","Site_contact":"","Site_phone":"","activated":"1"},{"Firepack_sn":"20023901","Installation_Date":"","Type":"DH","Standard":"VAS","Capacity_m3h":"195","Pressure_bar":"4,2","Rpm":"2000","Power_kw":"72","Pump_Type":"KSB KFP50-200","Motor_Type":"DOOSAN PU066 VAS/CEA","Controller_Type":"WB882-E10 VAS","Pump_sn":"085259","Motor_sn":"EARPA209635","Controller_sn":"","Servicelevel":"","Cust_id":"0","Cust_branche":"","Cust_name":"","Cust_address1":"","Cust_zipcode":"","Cust_city":"","Cust_country":"","Cust_Phone":"","Cust_coachlevel":"","Site_Name":"D-set","Site_address1":"","Site_address2":"","Site_address3":"","Site_zipcode":"","Site_city":"","Site_country":"","Site_contact":"","Site_phone":"","activated":"0"}]');
$arr2 = json_decode('[{"user_id":"40009","firepack_id":"20012205","activated":"1"},{"user_id":"40009","firepack_id":"21020393","activated":"0"}]');
$firepackIds = array();
foreach($arr2 as $item){
$firepackIds[] = $item->firepack_id;
}
$goodRows = array();
foreach($arr1 as $item){
if(in_array($item->Firepack_sn, $firepackIds)){
$goodRows[] = $item;
}
}
echo json_encode($goodRows);
Hope this helps.
You do not need multiple loops or inefficient iterated in_array() calls. PHP already offers a native function to compare rows between multiple 2D arrays -- array_uintersect(). Because the custom callback uses rows from either array while making comparisons, you must build the callback's logic to fallback to potentially use either array's target column value.
Code: (Demo)
var_export(
array_uintersect(
$array1,
$array2,
fn($a, $b) =>
($a['Firepack_sn'] ?? $a['firepack_id'])
<=>
($b['Firepack_sn'] ?? $b['firepack_id'])
)
);
Output:
array (
0 =>
array (
'Firepack_sn' => '20012205',
'Installation_Date' => '',
'Type' => 'EH',
'Capacity_m3h' => '81',
'Pressure_bar' => '3,4',
'Rpm' => '2930',
'Power_kw' => '72',
),
)

push certain elements into array php

I want to know that is there a way to insert certain elements of an array into a new array. I mean I have an array containing 10 objects. Each object has 3 or four fields for example id, name , age , username. now I want to insert the id's of all the objects into the new array with a single call.Is there anyway to do that.
$array = [
[0] => [
id =>
name =>
],
[1] = > [
id =>
name =>
]
]
and so on now I want to insert all the id's of all the object into a new array with a single call. Is there a way to do that?
Use array_map() function.
Here is your solution:-
$ids = array_map( function( $arr ){
return $arr["id"];
}, $arr );
echo '<pre>'; print_r($ids);
A basic foreach loop will do the job just fine
$firstArray = array(
array(
'id' => 1,
'name' => 'abc'
),
array(
'id' => 2,
'name' => 'def'
),
array(
'id' => 3,
'name' => 'gh'
)
);
$onlyIds = array();
$onlyKeys = array();
//To get the array value 'id'
foreach($firstArray as $value){
$onlyIds[] = $value['id'];
}
//To get the array keys
foreach($firstArray as $key => $value){
$onlyKeys[] = $key;
}
You could use array_walk which could be considered a "single call"
$array = array(0 => array('id', 'name', 'age'), 1 => array('id', 'name', 'age'));
array_walk($array, function($item, $key) {
// $key is 0 or 1
// $item is either id, name, age
});
You can use array_column.
$arr = [ ['id' => 1, 'username' => 'a'], ['id' => 2, 'username' => 'b'] ];
$ids = array_column($arr, 'id')
$ids == [1, 2]

Multidimensional Array - Match by odd key

I am trying to find the difference of 2 multidimensional arrays. I am attempting to solve this with a modified recursive array difference function.
If I have the following array setup:
$array1 = array(
0 => array(
'Age' => '1004',
'Name' => 'Jack'
),
1 => array (
'Age' => '1005',
'Name' => 'John'
)
);
$array2 = array(
0 => array(
'Age_In_Days' => '1004',
'Name' => 'Jack'
),
1=> array(
'Transaction_Reference' => '1005',
'Name' => 'Jack'
)
);
I am trying to match the arrays however the keys are not the same. I want to return the difference between the two multidimensional arrays where
$array1[$i]['Age'] == $array2[$i]['Age_In_Days'];
I want to keep the original array structure if the above condition holds true so the output I am looking for is:
$diff = array (1 => array (
'Age' => '1005',
'Name' => 'John'
));
However I am having issues with how to modify the recursive function to achieve this. Any help is appreciated! Thanks!
You need to loop through first array and compare values with second array. Then follows your condition. If condition is true then push this unique value to third array. Values in third array are now diff between first and second array.
$diff = [];
foreach ($array1 as $value1) {
foreach ($array2 as $value2) {
if ($value1['Age'] !== $value2['Age_In_Days']) {
array_push($diff, $value1);
}
}
}

Flip associative array and store new values in subarrays to prevent losing duplicated values

I have a flat associative array which may contain duplicate values.
Array (
[for-juniors] => product_category
[for-men] => product_category
[coats] => product_category
[for-women] => product_category
[7-diamonds] => brand
)
I need to restructure the data to store the original values as new keys and the original keys pushed into subarrays associated with the new keys.
array(
'product_category' => array(
'for-juniors',
'for-men',
'coats',
'for-women'
),
'brand' => array(
'7-diamonds'
)
);
$grouped = array();
foreach ($input as $choice => $group) {
$grouped[$group][] = $choice;
}
var_dump($grouped);
Because within a foreach() loop, the values are declared BEFORE the keys, you can actually populate the new data structure with a body-less foreach() loop.
Code: (Demo)
$array = [
'for-juniors' => 'product_category',
'for-men' => 'product_category',
'coats' => 'product_category',
'for-women' => 'product_category',
'7-diamonds' => 'brand'
];
$grouped = [];
foreach ($array as $grouped[$group][] => $group);
var_export($grouped);
Output:
array (
'product_category' =>
array (
0 => 'for-juniors',
1 => 'for-men',
2 => 'coats',
3 => 'for-women',
),
'brand' =>
array (
0 => '7-diamonds',
),
)
This'll do:
function array_flip_safe(array $array) : array
{
return array_reduce(array_keys($array), function ($carry, $key) use (&$array) {
$carry[$array[$key]] ??= []; // PHP 7.0 - ^7.3: $carry[$array[$key]] = $carry[$array[$key]] ?? [];
$carry[$array[$key]][] = $key;
return $carry;
}, []);
}
The callback creates an empty array if the array doesn't already exist. Then it appends current iteration's $key ($value of array_keys($array)) to that array.
Here's an example for better understanding:
$businessHours = [
'mo' => '13:00 - 16:00',
'tu' => '8:00 - 12:00',
'we' => '13:00 - 16:00',
'th' => '8:00 - 12:00',
'fr' => '13:00 - 16:00',
'sa' => '',
'su' => '',
];
$flipped = array_flip_safe($businessHours);
ray($flipped); (or var_dump, var_export, etc.) outputs:
array:3 [▼
"13:00 - 16:00" => array:3 [▼
0 => "mo"
1 => "we"
2 => "fr"
]
"8:00 - 12:00" => array:2 [▼
0 => "tu"
1 => "th"
]
"" => array:2 [▼
0 => "sa"
1 => "su"
]
]
Note that the order of inner arrays' values is the same as the order of original array's keys.

Categories