Laravel Lumen Collection - Group By With Sum and preserve the values - php

I'm working on Lumen and my collection has duplicate values, example:
collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 5.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 58.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
])
I would like to sum the value property when the name is the same but preserve other values like (department and phone) and remove duplicates entity, example:
collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 63.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
])
What's the best way to do this?

Try the following:
$newCollection = collect([]);
$collectctions = collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 5.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 58.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
]);
foreach ($collectctions as $item) {
if($newCollection->contains('name', $item['name'])){
$index = $newCollection->where('name', $item['name'])->keys()[0];
$newCollection = $newCollection->map(function ($object, $i) use ($index, $item) {
if($i == $index){
$object['value'] += $item['value'];
}
return $object;
});
}
else{
$newCollection->push($item);
}
}
return $newCollection;

This can be achieved using collection functions (https://laravel.com/docs/8.x/collections). In this example I solved it using (groupBy, map, flatten, slice, count and sum).
$data = collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 5.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 58.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
]);
$data = $data->groupBy('name')->map(function ($item) {
if ($item->count() > 1) {
$item = $item->slice(0, 1)->map(function($subItem) use ($item) {
$subItem['value'] = $item->sum('value');
return $subItem;
});
}
return $item;
})
->flatten(1);
When calling print_r($data->toArray()); we get the following array as result:
Array
(
[0] => Array
(
[name] => John Doe
[department] => Sales
[phone] => 99999-99999
[value] => 25
)
[1] => Array
(
[name] => Mary Lisa
[department] => Finance
[phone] => 88888-88888
[value] => 63
)
[2] => Array
(
[name] => Lucas Rodrigues
[department] => Marketing
[phone] => 22222-22222
[value] => 90
)
)

Related

How to map a 2D array to 1D array in PHP

I can't figure out how to do the following array_map in php. Any help is much appreciated.
Input:
$arrayA = [
[
'slug' => 'bob',
'name' => 'Bob',
'age' => '10',
],
[
'slug' => 'alice',
'name' => 'Alice',
'age' => '15',
],
[
'slug' => 'carl',
'name' => 'Carl',
'age' => '17',
]
]
Desired Output:
$arrayB = [
'bob' => 'Bob',
'alice' => 'Alice',
'carl' => 'Carl'
]
What I have so far:
Here I am mapping to an array and I know it's not what I want but I can not figure out if there is some syntax for me to return just $x['slug'] => $x['name'] without the brackets?
$arrayB = array_map(fn($x) => [$x['slug'] => $x['name']], $arrayA);
My current output (not what I want):
$arrayB = [
[ 'bob' => 'Bob' ],
[ 'alice' => 'Alice' ],
[ 'carl' => 'Carl' ]
];
There is a PHP function that can do exactly what you want: array_column()
$arrayA = [
[
'slug' => 'bob',
'name' => 'Bob',
'age' => '10',
],
[
'slug' => 'alice',
'name' => 'Alice',
'age' => '15',
],
[
'slug' => 'carl',
'name' => 'Carl',
'age' => '17',
]
];
$arrayB = array_column($arrayA, 'name', 'slug');
That will give you:
Array
(
[bob] => Bob
[alice] => Alice
[carl] => Carl
)
Here's a demo: https://3v4l.org/LGcES
With array_map you cant generate a array with the schema what you want. Use instead array_map foreach. like that:
<?php
$arrayA = [
[
'slug' => 'bob',
'name' => 'Bob',
'age' => '10',
],
[
'slug' => 'alice',
'name' => 'Alice',
'age' => '15',
],
[
'slug' => 'carl',
'name' => 'Carl',
'age' => '17',
]
];
$arrayB = [];
foreach($arrayA as $i) {
$arrayB[$i['slug']] = $i['name'];
}
print_r($arrayB);
// output:
/* Array (
[bob] => Bob
[alice] => Alice
[carl] => Carl
)

List key and value of common occurrences in value

$personas = [
'Franz' => [
'interests' => 'all',
'gender' => 'maskulin'
],
'Sissi' => [
'interests' => 'kitesurfing', 'tennis',
'gender' => 'feminin'
],
'Egon' => [
'interests' => 'kitesurfing', 'cinema';
'gender' => 'maskulin'
],
'Maria' => [
'interests' => 'cinema', 'soccer',
'gender' => 'feminin'
]
];
List the data of persons who have indicated in interests all or Kitesurfing
foreach($personas as $person => $kitesurfing) {
echo .$person.' is '.$gender.', ';
}
echo 'and all '.$personal_number.' '.$kitesurfing.' like!';
expected result
Franz is maskulin, Sissi is feminin, Egon is maskulin, and all 3 kitesurfing like!
<?php
$personas = [
'Franz' => [
'interests' => ['all'],
'gender' => 'maskulin'
],
'Sissi' => [
'interests' => ['kitesurfing', 'tennis'],
'gender' => 'feminin'
],
'Egon' => [
'interests' => ['kitesurfing', 'cinema'],
'gender' => 'maskulin'
],
'Maria' => [
'interests' => ['cinema', 'soccer'],
'gender' => 'feminin'
]
];
$interests = ['all', 'kitesurfing'];
$filtered = array_filter($personas, function($v) use ($interests) {
return array_intersect($interests, $v['interests']);
});
var_export($filtered);
Output:
array (
'Franz' =>
array (
'interests' =>
array (
0 => 'all',
),
'gender' => 'maskulin',
),
'Sissi' =>
array (
'interests' =>
array (
0 => 'kitesurfing',
1 => 'tennis',
),
'gender' => 'feminin',
),
'Egon' =>
array (
'interests' =>
array (
0 => 'kitesurfing',
1 => 'cinema',
),
'gender' => 'maskulin',
),
)

php Two-dimensional arrays are sorted and grouped according to the value of the key

I have a two-dimensional array that needs to be grouped according to assemble_id ,I can't get the result I want by traversing. Below is the original array:
$list = [
0 =>[
'nickname' => 'Bob',
'phone' => 15295892895,
'is_group' => 1,
'created_at' => 1544944181,
'assemble_id' => 'c1d0zUbmP',
'status' => 1
],
1 =>[
'nickname' => 'Jack',
'phone' => 15295892895,
'is_group' => 1,
'created_at' => 1544944181,
'assemble_id' => 'ED6OJX4VV',
'status' => 1
],
2 =>[
'nickname' => 'Grace',
'phone' => 15295892895,
'is_group' => 0,
'created_at' => 1544944181,
'assemble_id' => 'c1d0zUbmP',
'status' => 1
],
3 =>[
'nickname' => 'Jelly',
'phone' => 15295892895,
'is_group' => 0,
'created_at' => 1544944181,
'assemble_id' => 'ED6OJX4VV',
'status' => 1
]
];
What i need is:
[
[
'assemble_id' => 'c1d0zUbmP',
'assemble_group' => [
[
'nickname' => 'Bob',
'phone' => 15295892895,
'is_group' => 1,
'created_at' => 1544944181,
'assemble_id' => 'c1d0zUbmP',
'status' => 1
],
[
'nickname' => 'Grace',
'phone' => 15295892895,
'is_group' => 0,
'created_at' => 1544944181,
'assemble_id' => 'c1d0zUbmP',
'status' => 1
]
]
],
[
'assemble_id' => 'ED6OJX4VV',
'assemble_group' => [
[
'nickname' => 'Jack',
'phone' => 15295892895,
'is_group' => 1,
'created_at' => 1544944181,
'assemble_id' => 'ED6OJX4VV',
'status' => 1
],
[
'nickname' => 'Jack',
'phone' => 15295892895,
'is_group' => 0,
'created_at' => 1544944181,
'assemble_id' => 'ED6OJX4VV',
'status' => 1
]
]
]
];
I need to group according to the same assemble_id and put is_group=1 in the first of each group.
hery is my code:
function formatData($list)
{
$data = [];
foreach ($list as $k=>$v) {
$list[$k]['created_at'] = formatDate($v['created_at'],'Y-m-d H:i');
$list[$k]['phone'] = setMobile($v['phone']);
$data[$k]['assemble_id'] = $v['assemble_id'];
$data[$v['assemble_id']][] = $list[$k];
}
return $data;
}
This did not get the results I wanted.
Assign temporary associative keys, then remove them when finished looping.
Code: (Demo)
foreach ($list as $row) {
$result[$row['assemble_id']]['assemble_id'] = $row['assemble_id'];
$result[$row['assemble_id']]['assemble_group'][] = [
'nickname' => $row['nickname'],
'phone' => $row['phone'], // add your function here
'is_group' => $row['is_group'],
'created_at' => $row['created_at'], // add your function here
'assemble_id' => $row['assemble_id'],
'status' => $row['status']
];
}
var_export(array_values($result));
Output:
array (
0 =>
array (
'assemble_id' => 'c1d0zUbmP',
'assemble_group' =>
array (
0 =>
array (
'nickname' => 'Bob',
'phone' => 15295892895,
'is_group' => 1,
'created_at' => 1544944181,
'assemble_id' => 'c1d0zUbmP',
'status' => 1,
),
1 =>
array (
'nickname' => 'Grace',
'phone' => 15295892895,
'is_group' => 0,
'created_at' => 1544944181,
'assemble_id' => 'c1d0zUbmP',
'status' => 1,
),
),
),
1 =>
array (
'assemble_id' => 'ED6OJX4VV',
'assemble_group' =>
array (
0 =>
array (
'nickname' => 'Jack',
'phone' => 15295892895,
'is_group' => 1,
'created_at' => 1544944181,
'assemble_id' => 'ED6OJX4VV',
'status' => 1,
),
1 =>
array (
'nickname' => 'Jelly',
'phone' => 15295892895,
'is_group' => 0,
'created_at' => 1544944181,
'assemble_id' => 'ED6OJX4VV',
'status' => 1,
),
),
),
)

How to create array in Guzzle Request?

I'm trying to send a post to an API, but the "items should be an array" error is returned.
$response2 = $client2->request('POST', 'https://api.iugu.com/v1/invoices?api_token='.$token, [
'form_params' => [
'email' => $email,
'due_date' => $due_date,
'items' => ['description' =>
'Item Um',
'quantity' => 1,
'price_cents' => 1000
],
'payer' => [
'cpf_cnpj' => $cpf_cnpj,
'name' => $name,
'phone_prefix' => $phone_prefix,
'phone' => $phone,
'email' => $email,
'address' => [
'zip_code' => $zip_code,
'street' => $street,
'number' => $number,
'district' => $district,
'city' => $city,
'state' => $state,
'country' => 'Brasil',
'complement' => $complement
]
]
]
]);
I've tried it in several ways.
['items' => 'description' =>
'Item Um',
'quantity' => 1,
'price_cents' => 1000
],
But none of the ways showed the result I wanted. It's weird, because when I run with PHP and CURL lib this code works like charm.
Any sugestion? Thanks in advance for community!
Each item should be an array with their own description, quantity, and price_cents keys. Wrap each within one more array like so:
'items' => [
[
'description' => 'Item Um',
'quantity' => 1,
'price_cents' => 1000
],
]
You'll get an array of items now:
Array
(
[0] => Array
(
[description] => Item Um
[quantity] => 1
[price_cents] => 1000
)
)

Merge arrays inside array dynamically which have the same keys

I am using PHP 5.6. I have an array like this:
$array = [
0 => [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'food' => 'burger',
],
],
1 => [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'drink' => 'coke',
],
],
2 => [
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'food' => 'pizza',
],
],
3 => [
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'drink' => 'pepsi',
],
],
];
Let's say that "food" and "drink" are categories and they can differ depending on how the questionnaire was setup. So there could in fact be "food", "drink", and "dessert" for example. As you can see, there is an array for each person, for each category. What I would like to do is to merge the arrays by each person so that it will instead show up with the following:
$array = [
0 => [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'food' => 'burger',
'drink' => 'coke', // Merged
],
],
1 => [
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'food' => 'pizza',
'drink' => 'pepsi', // Merged
],
],
];
I have looked at array_merge as well as array_merge_recursive, however from everything that I've read, you have to specify the arrays in order to merge them, for example it has to be array_merge(array[0], array[1]). As you can see, I can't exactly do this because there could be 2,3 or even 4 arrays per person which have to be merged together.
So how do I dynamically merge the arrays for each person so that it shows all their information together?
This is not exactly as the result you asked for and it feels pretty messy, but it might be something you can work further with :)
$result = [];
foreach ($array as $answers) {
foreach ($answers as $email => $values) {
if (!isset($result[$email])) {
$result[$email] = $values;
continue;
}
$result[$email] = array_merge($result[$email], $values);
}
}
And the result:
$result === [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'food' => 'burger',
'drink' => 'coke',
],
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'food' => 'pizza',
'drink' => 'pepsi',
],
]
<?php
$originalArray=array (
0 => array ('johndrake#gmail.com' => array ('email' => 'johndrake#gmail.com', 'firstname' => 'john', 'lastname' => 'drake', 'food' => 'burger')),
1 => array ('johndrake#gmail.com' => array ('email' => 'johndrake#gmail.com', 'firstname' => 'john', 'lastname' => 'drake', 'drink' => 'coke')),
2 => array ('samwin#gmail.com' => array ('email' => 'samwin#gmail.com', 'firstname' => 'sam', 'lastname' => 'win', 'food' => 'pizza')),
3 => array ('samwin#gmail.com' => array ('email' => 'samwin#gmail.com', 'firstname' => 'sam' ,'lastname' => 'win', 'drink' => 'pepsi'))
);
$tempArray=array();
$newArray=array();
foreach($originalArray as $key=>$val){
$valKey=key($val);
if(isset($tempArray[$valKey])){
$newArray[]=array_merge($tempArray[$valKey],$val[$valKey]);
}
else{
$tempArray[$valKey]=$val[$valKey];
}
}
echo "<pre>";print_r($newArray);

Categories