Merge Array on the basis of same key and value Laravel/PHP - php

I have two array, with common key and value i.e. 'id'
$arr_1 = [
'0'=>[
id=1,
name='Foo'
]
'1'=>[
id=2,
name='Bar'
]
];
$arr_2 = [
'0'=>[
id=1,
Percentage=60
]
'1'=>[
id=2,
Percentage=70
]
]
i want to combine it, to form a new array, based on common key and value
The result should be,
$arr_3 = [
'0'=>[
id=1,
name='Foo'
Percentage=60
]
'1'=>[
id=2,
name='Bar'
Percentage=70
]
];

With two arrays
$arr_1 = collect(array(
'0' => array(
'id' => 1,
'name' =>'Foo'
),
'1' => array(
'id'=> 2,
'name'=> 'Bar'
),
));
$arr_2 = collect(array(
'0'=>array(
'id'=> 1,
'Percentage'=> 60
),
'1'=>array(
'id'=> 2,
'Percentage'=> 70
)
));
In your controller
$arr_3 = $arr_1->map(function($row) use ($arr_2) {
$percent = $arr_2->where('id', $row['id'])->pluck('Percentage');
return collect($row)->put('NewPercent', $percent);
});
Backtesting
[
{"id":1,"name":"Foo","NewPercent":[60]},
{"id":2,"name":"Bar","NewPercent":[70]}
]
Edit 1:
For only the value:
$arr_3 = $arr_1->map(function($row, $key) use ($arr_2) {
$currentArr = $arr_2->where('id', $row['id'])->first();
$percent = Arr::get($currentArr, 'Percentage');
return collect($row)->put('Percentage', $percent);
});
Testing:
[
{"id":1,"name":"Foo","Percentage":60},
{"id":2,"name":"Bar","Percentage":70}
]

Related

Lower child array keys and combine items

I've one array
$arr = [
'parent' => [
'CHILD' => [
5,6
],
'child' => [
1,2,3,4
],
'Child' => [
5,6,7,8
],
...
]
];
I want to lower the child keys and combine each child having the same case insensitive keys like
$arr = [
'parent' => [
'child' => [
1,2,3,4,5,6,7,8
],
]
];
I've tried with array_change_key_case which always takes the last element and ignores the others.
An array may have multiple children with the same key (with different case)
Try the code below should work:
<?php
$arr = [
'parent' => [
'CHILD' => [
5,6
],
'child' => [
1,2,3,4
],
]
];
$arNew = [];
foreach ($arr as $sParent => $ar) {
foreach ($ar as $sChild => $ar1) {
$sChild = strtolower($sChild);
if (empty($arNew[$sParent][$sChild])) {
$arNew[$sParent][$sChild] = $ar1;
} else {
$arNew[$sParent][$sChild] = array_merge($arNew[$sParent][$sChild], $ar1);
}
}
}
print_r($arNew);

Combine array of objects using keys

I want to combine two arrays of objects. Let me give you an example:
Example:
// First array:
$array1 = [
{ name => 'Joe', p_id => 1 },
{ name => 'Bob', p_id => 2 },
{ name => 'Sam', p_id => 4 }
]
// Second array:
$array2 = [
{ id => 1, name => 'X' },
{ id => 2, name => 'Y' },
{ id => 4, name => 'Z' }
]
Expected output:
$output = [
{ name => 'Joe + X', id => 1 },
{ name => 'Bob + Y', id => 2 },
{ name => 'Sam + Z', id => 4 }
]
Goal:
I want the fastest possible way to combine the name property in the second array with the name property in the first array.
Note: The p_id property in the first array is the same as the id property in the second array.
What i try:
I've used nested loops that have a very low speed.
array_map is the solution!
Given:
$first = [
{ name => 'Joe', p_id => 1 },
{ name => 'Bob', p_id => 2 },
{ name => 'Sam', p_id => 4 },
];
$second = [
{ id => 1, name => 'X' },
{ id => 2, name => 'Y' },
{ id => 4, name => 'Z' },
];
The solution is just simply:
$result = array_map(
static function (\stdClass $first, \stdClass $second): array {
return [
'name' => $first->name . ' + ' . $second->name,
'id' => $first->p_id,
];
},
$first, $second
);
PS: I assume the objects are \stdClass, replace it by the correct one.
Here is a solution for when the ids of the elements inside the array are not in order. Notice that I have changed the order of $array1. Just a bit better than the regular nested loops, on the loop of the $array2 it will remove the "found" elements to improve speed of the next loop.
From:
// First array:
$array1 = [
(object) ['name' => 'Joe', 'p_id' => 1],
(object) ['name' => 'Sam', 'p_id' => 4],
(object) ['name' => 'Bob', 'p_id' => 2],
];
// Second array:
$array2 = [
(object) ['id' => 1, 'name' => 'X'],
(object) ['id' => 2, 'name' => 'Y'],
(object) ['id' => 4, 'name' => 'Z'],
];
Solution:
$result = [];
foreach ($array1 as $array1Element) {
for ($i=0;$i<count($array2);$i++) {
if ($array1Element->p_id === $array2[$i]->id) {
$array2[$i]->name = $array1Element->name . ' + ' . $array2[$i]->name;
$result[] = $array2[$i];
unset($array2[$i]);
$array2 = array_values($array2);
break;
}
}
}

Combine two array using a field in PHP

I have an array in which i want to combine the common fields together.
So that the common names get grouped together and they contain the common values of that particular name.
Below is my array
[
[
count_employee: 2,
name: "Harry"
],
[
count_employee: 61,
name: "Jack"
],
[
count_employee: 11,
name: "John"
],
[
count_warehouse: 1,
name: "Harry"
],
[
count_warehouse: 77,
name: "John"
],
[
count_warehouse: 45,
name: "Jack"
]
]
I want the output to be
[
[
name: "Harry",
count_employee:2
count_warehouse:1
],
[
name: "Jack",
count_employee: 61
count_warehouse: 45
],
[
name: "John",
count_employee:11
count_warehouse:77
],
]
So far i have tried this out
foreach ($data as $key => $value) {
$group[$value['name']]['name'] = $value['name'];
$group[$value['name']][$key]['count_employee'] = $value['count_employee'];
$group[$value['name']][$key]['count_warehouse'] = $value['count_warehouse'];
}
Loop over the array, and use the name as the index of each element. If no element by that index does not exist, define it as an empty array.
Then all you need to do is add the fields (if they exist) to the proper column.
Your issue was that you were creating an array with one too many dimensions, instead of adding each value to the current count - in addition to the fact that you will not always have both the warehouse and employee count defined for each iteration.
$result = [];
foreach ($arr as $v) {
// Initialize the person
if (!isset($result[$v['name']])) {
$result[$v['name']] = ["name" => $v['name'], "count_employee" => 0, "count_warehouse" => 0];
}
// Add values
if (isset($v['count_employee']))
$result[$v['name']]['count_employee'] += $v['count_employee'];
if (isset($v['count_warehouse']))
$result[$v['name']]['count_warehouse'] += $v['count_warehouse'];
}
// print_r($result);
Live demo at https://3v4l.org/TeNKF
You can use array_walk with array_key_exists
$res=[];
array_walk($arr, function($v,$k) use (&$res){
if(array_key_exists($v['name'], $res))
$res[$v['name']]['count_warehouse'] = $v['count_warehouse'];
else
$res[$v['name']] = $v;
});
print_r(array_values($res));
Live Demo
Assuming all the array has a name key for each sub array contained within, we can use the name as a key for an array and merge arrays with corresponding name values.
<?php
$data=
[
[
'count_employee'=> 2,
'name'=> 'Harry'
],
[
'count_employee'=> 61,
'name'=> 'Jack'
],
[
'count_employee'=> 11,
'name'=> 'John'
],
[
'count_warehouse'=> 1,
'name'=> 'Harry'
],
[
'count_warehouse'=> 77,
'name'=> 'John'
],
[
'count_warehouse'=> 45,
'name'=> 'Jack'
]
];
$output = [];
foreach($data as $item) {
$output[$item['name']] = array_merge($item, $output[$item['name']] ?? []);
}
var_export($output);
Output:
array (
'Harry' =>
array (
'count_warehouse' => 1,
'name' => 'Harry',
'count_employee' => 2,
),
'Jack' =>
array (
'count_warehouse' => 45,
'name' => 'Jack',
'count_employee' => 61,
),
'John' =>
array (
'count_warehouse' => 77,
'name' => 'John',
'count_employee' => 11,
),
)

Add grouping elements to 2d array and sum values in respective group

I need to add new elemets to my array when a new category value is encountered. When a category value is encountered after the first time, its value1 and value2 values should be added to the first encounter's respective values.
Also, in the result array, I no longer wish to keep the category column. The category-grouping rows should use the category value as its name value.
Sample input:
$datas = [
[
'category' => 'Solution',
'name' => 'Name1',
'value1' => 20,
'value2' => 21
],
[
'category' => 'Solution',
'name' => 'Name2',
'value1' => 30,
'value2' => 31
],
[
'category' => 'Solution1',
'name' => 'Name3',
'value1' => 40,
'value2' => 41
]
];
Desired result:
[
['name' => 'Solution', 'value1' => 50, 'value2' => 52],
['name' => 'Name1', 'value1' => 20, 'value2' => 21],
['name' => 'Name2', 'value1' => 30, 'value2' => 31],
['name' => 'Solution1', 'value1' => 40, 'value2' => 41],
['name' => 'Name3', 'value1' => 40, 'value2' => 41]
]
I tried like this:
private function groupByProductSuperCategory($datas)
{
$return = [];
foreach ($datas as $data) {
$return[$data['category']][$data['name']] = array_sum(array_column('category', $data);
}
return $return;
}
The idea is to calculate first all sum values for by category, and after that just put values from name like another array. Have you an idea of how to do that?
From the posted array... To end in the desired array, there is some tiny fixes to do first. But I assumed it was due to typos while copying here...
So here is the array I started with:
$result = [
0 => [
"category" => 'Solution',
"name" => 'Name1',
"value1" => 20,
"value2" => 21
],
1 => [
"category" => 'Solution',
"name" => 'Name2',
"value1" => 30,
"value2" => 31
],
2 => [
"category" => 'Solution1',
"name" => 'Name3',
"value1" => 40,
"value2" => 41
]
];
Now, that re-organization of the data is a bit more complex than it looks... You need to perform several loops to:
Find distinct "category" names
Perform the summations for each
Add the sum item and the single items
So here is the code I ended with:
function groupByProductSuperCategory($datas){
$category = [];
$return = [];
// Find distinct categories
foreach ($datas as $data) {
if(!in_array($data["category"],$category)){
array_push($category,$data["category"]);
}
}
// For each distinct category, add the sum item and the single items
foreach ($category as $cat) {
// Get the sums
if(!in_array($cat,$return)){
$sum1 = 0;
$sum2 = 0;
foreach ($datas as $data) {
if($data["category"] == $cat){
$sum1 += $data["value1"];
$sum2 += $data["value2"];
}
}
}
// Push the sums in the return array
array_push($return,[
"name" => $cat,
"value1" => $sum1,
"value2" => $sum2,
]);
// Push the single elements
foreach ($datas as $data) {
if($cat == $data["category"]){
array_push($return,[
"name" => $data["name"],
"value1" => $data["value1"],
"value2" => $data["value2"],
]);
}
}
}
return $return;
}
Here is a PHPFiddle to try it out... Hit [F9] to run.
It is much more direct, efficient, and readable to implement a single loop and push reference variables into the result array to allow summing based on shared categories without keeping track of the actual indexes of the category rows.
Code: (Demo)
$result = [];
foreach ($array as $row) {
if (!isset($ref[$row['category']])) {
$ref[$row['category']] = [
'name' => $row['category'],
'value1' => 0,
'value2' => 0
];
$result[] = &$ref[$row['category']];
}
$ref[$row['category']]['value1'] += $row['value1'];
$ref[$row['category']]['value2'] += $row['value2'];
unset($row['category']);
$result[] = $row;
}
var_export($result);

How can I match array in php?

I have 2 arrays, I want match this arrays and get results with keys.
Can I search in first array with second array keys or match diffrent way?
$boardLists = [
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
[
'_id' => 'b2b2b2',
'name' => 'Board Name #2',
'code' => 'B2
]
];
and
$boards = [
'a1a1a1',
'b2b2b2',
'c3c3c3'
];
My result with array_intersect:
array(1) { [0]=> string(6) "a1a1a1" }
My expected result if match 'a1a1a1':
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
That I could understand you want to search in the first array according to what you have in the second array, so here is one example:
$boardLists = [
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
[
'_id' => 'b2b2b2',
'name' => 'Board Name #2',
'code' => 'B2'
]
];
$boards = [
'a1a1a1',
'b2b2b2',
'c3c3c3'
];
$boardListIds = array_column($boardLists, '_id');
$results = [];
foreach ($boards as $board) {
$find_key = array_search($board, $boardListIds);
if($find_key !== false)
$results[] = $find_key;
}
#printing the results
foreach ($results as $result) {
print_r($boardLists[$result]);
}
There many ways to do it, this is just one. I hope it helps. :)
It would be more efficient to have the array index of your first array the _id. However with the way the array is setup currently you could do:
foreach($boards as $key1=>board){
foreach($boardLists as $key2=>$boardList){
if($boardList['_id']==$key1){
echo $key1 . PUP_EOL;
print_r($boardList);
}
}
}
Try this
$finalArray = array();
foreach($boardLists as $key=>$val):
if(in_array($val['_id'],$boards))
{
$finalArray[] = $val2;
}
endforeach;

Categories