Split assoc array by keys - php

I have data like this:
$movements = [
array(
"amount" => 100,
"type" => "expense",
"Dates" => "2020-01-01"
),
array(
"amount" => 100,
"type" => "income",
"Dates" => "2020-01-01"
),
array(
"amount" => 200,
"type" => "expense",
"Dates" => "2020-02-01"
),
array(
"amount" => 200,
"type" => "income",
"Dates" => "2020-02-01"
),
array(
"amount" => 300,
"type" => "income",
"Dates" => "2020-03-01"
),
array(
"amount" => 400,
"type" => "expense",
"Dates" => "2020-04-01"
),
array(
"amount" => 400,
"type" => "income",
"Dates" => "2020-04-01"
),
]
I want to separate it into 3 different arrays like so:
//This are my chart labels
$dates = ["2020-01-01","2020-02-01","2020-03-01"."2020-04-01"]
//This are my datapoints
$income = [100,200,300,400]
$expense = [100,200,0,400]
For the life of me i just cant seem to wrap my head around this today, I have tried doing loops and while/if using "array_colum()" but I cant get to add a 0 for the entry that does not have a matching date.
PS: I need the data in that format snice im charting it on chart.js within a Laravel view.
Any help is greatly appreciated.

$movements = [
[ 'amount' => 100, 'type' => 'expense', 'Dates' => '2020-01-01' ],
[ 'amount' => 100, 'type' => 'income', 'Dates' => '2020-01-01' ],
[ 'amount' => 200, 'type' => 'expense', 'Dates' => '2020-02-01' ],
[ 'amount' => 200, 'type' => 'income', 'Dates' => '2020-02-01' ],
[ 'amount' => 300, 'type' => 'income', 'Dates' => '2020-03-01' ],
[ 'amount' => 400, 'type' => 'expense', 'Dates' => '2020-04-01' ],
[ 'amount' => 400, 'type' => 'income', 'Dates' => '2020-04-01' ],
];
$dates = array_values(array_unique(array_column($movements, 'Dates')));
$income = [];
$expense = [];
foreach ($dates as $date) {
$item = array_values(array_filter($movements, fn($item) => $item['Dates'] === $date));
$amount1 = $item[0]['amount'];
$amount2 = count($item) === 2 ? $item[1]['amount'] : 0;
$expense[] = $item[0] === 'expense' ? $amount1 : $amount2;
$income[] = $item[0] === 'expense' ? $amount2 : $amount1;
}
print_r($dates);
print_r($income);
print_r($expense);
This will print:
Array
(
[0] => 2020-01-01
[1] => 2020-02-01
[2] => 2020-03-01
[3] => 2020-04-01
)
Array
(
[0] => 100
[1] => 200
[2] => 300
[3] => 400
)
Array
(
[0] => 100
[1] => 200
[2] => 0
[3] => 400
)

Related

Add an element to a multidimensional array

Add an element to a multidimensional array
Tell me how to make it so as to get an array of $params2 from the array $params
$params = [
'id' => 234223,
'price' => [
"currencyId" => "RUR",
"value" => 2000,
]
];
$params2 = [
'id' => 234223,
'price' => [
"currencyId" => "RUR",
"value" => 2000,
"discountBase" => 3000
]
];
You can assign it to a new variable $params2 then assign $params2['price']['discountBase'] = 3000;
For example:
$params = [
'id' => 234223,
'price' => [
"currencyId" => "RUR",
"value" => 2000,
]
];
$params2 = $params;
$params2['price']['discountBase'] = 3000;
var_export($params2);
Output:
array (
'id' => 234223,
'price' =>
array (
'currencyId' => 'RUR',
'value' => 2000,
'discountBase' => 3000,
),
)

Array sum of selected dates from the array of rooms with set dates and prices

I've got an array of selected dates and an array of rooms with set dates and prices. From the array $selectedDates, it should look for a date from the rooms. If one of the $selectedDates is found from each room, it should use the price under the options keys if not it should use the default_price key.
$selectedDates = ['10-04-2022', '11-04-2022', '12-04-2022'];
$setRooms = [
0 => [
'id' => 1,
'title' => 'Room1',
'default_price' => 50,
'options' => [
0 => [
'date' => '12-04-2022',
'price' => 100,
],
1 => [
'date' => '13-04-2022',
'price' => 200,
],
3 => [
'date' => '14-04-2022',
'price' => 200,
],
]
],
1 => [
'id' => 2,
'title' => 'Room2',
'default_price' => 120,
'options' => [
0 => [
'date' => '11-04-2022',
'price' => 200,
],
1 => [
'date' => '12-04-2022',
'price' => 300,
],
3 => [
'date' => '13-04-2022',
'price' => 400,
],
]
],
]
Expected Output:
[
// '10-04-2022' = 50 (default_price), '11-04-2022' = 50 (default_price), '12-04-2022' = 100 (using the option price). 50 + 50 + 100 = 200
0 => [
'id' => 1,
'title' => 'Room1',
'total_price' => 200
],
// '10-04-2022' = 50 (default_price), '11-04-2022' = 200 (using the option price), '12-04-2022' = 300 (using the option price). 120 + 200 + 300 = 620
1 => [
'id' => 2,
'title' => 'Room2',
'total_price' => 620
]
]
This is what I've done so far. But it turns out that room 2 is giving me a different output, it's like the sum of room 1 will be added to room 2.
$price = 0;
$roomBookings = [];
foreach ($hotelRooms as $key => $room) {
$count = count($listOfSelectedDates);
foreach ($listOfSelectedDates as $selectedDate) {
$getPrice = HelperTrait::searchForDate($selectedDate, $room['options']);
if ($getPrice['success']) {
$price += $getPrice['price'];
}
else {
$price += $room['default_price'];
}
$room['total_price'] = $price;
}
$roomBookings[] = $room;
}
/////
public static function searchForDate($date, $array): array
{
foreach ($array as $key => $val) {
$date = Carbon::parse($date)->format('d-m-Y');
$arrDate = Carbon::parse($val['date'])->format('d-m-Y');
if ($arrDate === $date) {
return [
'success' => true,
'price' => $val['price']
];
}
}
return [
'success' => false
];
}
Let me know if you have any questions.
Thanks in advance!
$setRooms = [
[
'id' => 1,
'title' => 'Room1',
'default_price' => 50,
'options' => [
[ 'date' => '12-04-2022', 'price' => 100, ],
[ 'date' => '13-04-2022', 'price' => 200, ],
[ 'date' => '14-04-2022', 'price' => 200, ],
]
],
[
'id' => 2,
'title' => 'Room2',
'default_price' => 120,
'options' => [
[ 'date' => '11-04-2022', 'price' => 200, ],
[ 'date' => '12-04-2022', 'price' => 300, ],
[ 'date' => '13-04-2022', 'price' => 400, ],
]
],
];
$selectedDates = [ '10-04-2022', '11-04-2022', '12-04-2022' ];
$result = [];
foreach ($setRooms as $room) {
$total = 0;
foreach ($selectedDates as $date) {
$filtered = array_filter($room['options'], fn($option) => $date === $option['date']);
if (count($filtered) === 1) {
$total += $filtered[array_key_first($filtered)]['price'];
} else {
$total += $room['default_price'];
}
}
$result[] = [ 'id' => $room['id'], 'title' => $room['title'], 'total_price' => $total ];
}
print_r($result);
Output:
Array
(
[0] => Array
(
[id] => 1
[title] => Room1
[total_price] => 200
)
[1] => Array
(
[id] => 2
[title] => Room2
[total_price] => 620
)
)

Counting expenses for categories stored in tree like array

I have an app where users can store their expenses and assign it to categories. Categories have tree structure, without depth limit and users can assign expense to any category (children, parent or middle). What I want to do is to count sum of expenses for all categories in tree structure. Lets simplify things and assume I have array with categories:
$categories = [
0 => [
'id' => 1,
'name' => 'Car',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 2,
'name' => 'Gas',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 3,
'name' => 'Orlen',
'expenses_sum' => 300,
'subcategories' => [
0 => [
'id' => 4,
'name' => 'Orlen A',
'expenses_sum' => 100,
'subcategories' => []
],
1 => [
'id' => 5,
'name' => 'Orlen B',
'expenses_sum' => 100,
'subcategories' => []
],
],
],
],
],
],
],
];
What I want do do is to go to the deepest level ("Orlen A" and "Orlen B"), sum expenses from that level, add it to the parent level ("Orlen") and store as the new "expenses_sum", so it should be: 100 + 100 + 300 = 500 and repeat it to the top level.
My code to do that looks like this:
function sumCategory(&$category) {
if (isset($category['subcategories'])) {
foreach ($category['subcategories'] as $subCategory) {
$subCategory['expenses_sum'] = sumCategory($subCategory);
$category['expenses_sum'] += $subCategory['expenses_sum'];
}
}
return $category['expenses_sum'];
}
foreach ($categories as $index => $category) {
$categories[$index]['expenses_sum'] = sumCategory($category);
}
echo '<pre>';
print_r($categories);
echo '</pre>';
Code counts properly sum at all levels, but the problem is that finally I got $categories array with modfied only "expenses_sum" at the top level and categories in the middle stays not modified. I tried to pass $categories to function by refference, but it doesnt help. Any tips what should I correct?
I have simplified problem, so you can easily grab all above code to test things on your own.
To clarify things: at the end I expect my array will be as follow:
$categories = [
0 => [
'id' => 1,
'name' => 'Car',
'expenses_sum' => 500, //500 + 0
'subcategories' => [
0 => [
'id' => 2,
'name' => 'Gas',
'expenses_sum' => 500, //500 + 0
'subcategories' => [
0 => [
'id' => 3,
'name' => 'Orlen',
'expenses_sum' => 500, //100 + 100 + 300
'subcategories' => [
0 => [
'id' => 4,
'name' => 'Orlen A',
'expenses_sum' => 100,
'subcategories' => []
],
1 => [
'id' => 5,
'name' => 'Orlen B',
'expenses_sum' => 100,
'subcategories' => []
],
],
],
],
],
],
],
];
$categories = [
0 => [
'id' => 1,
'name' => 'Car',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 2,
'name' => 'Gas',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 3,
'name' => 'Orlen',
'expenses_sum' => 300,
'subcategories' => [
0 => [
'id' => 4,
'name' => 'Orlen A',
'expenses_sum' => 100,
'subcategories' => []
],
1 => [
'id' => 5,
'name' => 'Orlen B',
'expenses_sum' => 100,
'subcategories' => []
],
],
],
],
],
],
],
];
function expensesSum($category) {
$sum = $category['expenses_sum'] ;
foreach($category['subcategories'] as $subCategory) {
$sum += expensesSum($subCategory);
}
return $sum;
}
function calculateExpenses(&$categories) {
foreach($categories as $index => $category) {
// do subs first
calculateExpenses($categories[$index]['subcategories']);
// then parent
$categories[$index]['expenses_sum'] = expensesSum($category);
}
return $categories;
}
print_r(calculateExpenses($categories));
Output:
Array
(
[0] => Array
(
[id] => 1
[name] => Car
[expenses_sum] => 500
[subcategories] => Array
(
[0] => Array
(
[id] => 2
[name] => Gas
[expenses_sum] => 500
[subcategories] => Array
(
[0] => Array
(
[id] => 3
[name] => Orlen
[expenses_sum] => 500
[subcategories] => Array
(
[0] => Array
(
[id] => 4
[name] => Orlen A
[expenses_sum] => 100
[subcategories] => Array
(
)
)
[1] => Array
(
[id] => 5
[name] => Orlen B
[expenses_sum] => 100
[subcategories] => Array
(
)
)
)
)
)
)
)
)
)
function calculateExpenses($categories) {
$expenses = 0;
foreach($categories as $category) {
$expenses += $category['expenses_sum'];
$expenses += calculateExpenses($category['subcategories']);
}
return $expenses;
}
echo calculateExpenses($categories);

Php array transformation and combination

So I have array like this one
[
'custid' => [
'customer_number_1' => '20098374',
'customer_number_8' => '20098037',
'customer_number_15' => '20098297'
],
'destid' => [
'destination_numbers_1' => [
(int) 0 => '20024838',
(int) 1 => '20041339'
],
'destination_numbers_8' => [
(int) 0 => '20008293'
],
'destination_numbers_15' => [
(int) 0 => '20016969',
(int) 1 => '20022919',
(int) 2 => '20025815',
(int) 3 => '20026005',
(int) 4 => '20027083',
(int) 5 => '20045497'
]
]
]
Goal is to merge cust id with destid in pairs and should look like so
[
(int) 0 => [
'user_id' => (int) 1,
'sap_customer_id' => '20098374',
'sap_destination_id' => '20024838'
],
(int) 1 => [
'user_id' => (int) 1,
'sap_customer_id' => '20098374',
'sap_destination_id' => '20041339',
],
(int) 2 => [
'user_id' => (int) 1,
'sap_customer_id' => '20098037',
'sap_destination_id' => '20008293,
],
(int) 3 => [
'user_id' => (int) 1,
'sap_customer_id' => '20098297'
'sap_destination_id' => '20016969',
],
...
I have tried with code below, but I am getting destination_id number as array and duplicated customer numbers. Also I have tried with array walk but result is same.
$data = [];
foreach ($sap_data['custid'] as $custid) {
foreach ($sap_data['destid'] as $destid) {
$data[] = [
'user_id' => 1,
'sap_customer_id' => $custid,
'sap_destination_id' => $destid
];
}
}
Thx for helping!
You should make inner loop in other way
foreach($sap_data['custid'] as $k => $custid) {
// Make destination key
$dkey = str_replace('customer_number', 'destination_numbers', $k);
// And get array, for example, destination_numbers_1 for customer_number_1
foreach ($sap_data['destid'][$dkey] as $destid) {
$data[] = [
'user_id' => 1,
'sap_customer_id' => $custid,
'sap_destination_id' => $destid
];
}
}
demo on eval.in

Finding the lowest value for specific key in a deeply nested array

Given an array with the following structure:
$orders = [
0 => [
'volume' => 1926,
'lowPrice' => 1000.00,
'date' => 2016-12-29 00:45:23
],
1 => [
'volume' => 145,
'lowPrice' => 1009.99,
'date' => 2016-12-31 14:23:51
],
2 => [
'volume' => 19,
'lowPrice' => 985.99,
'date' => 2016-12-21 09:37:13
],
3 => [
'volume' => 2984,
'lowPrice' => 749.99,
'date' => 2017-01-01 19:37:22
],
// ...
]
I'm looking for the most performant way to find the lowest value for lowPrice. The size of $orders will more than likely be larger than 500 items. For the given array, the result would be as follows:
$lowestPrice = $this->findLowestPrice($orders);
echo $lowestPrice; // 749.99
Extract an array of lowPrice and find the min():
echo min(array_column($orders, 'lowPrice'));
Since those appear to be floats, you'll probably want number_format() or money_format().
If you're only interested in the value of the lowest price (not the index in the array or something) you can use array_reduce:
$orders = [
0 => [
'volume' => 1926,
'lowPrice' => 1000.00,
'date' => "2016-12-29 00:45:23"
],
1 => [
'volume' => 145,
'lowPrice' => 1009.99,
'date' => "2016-12-31 14:23:51"
],
2 => [
'volume' => 19,
'lowPrice' => 985.99,
'date' => "2016-12-21 09:37:13"
],
3 => [
'volume' => 2984,
'lowPrice' => 749.99,
'date' => "2017-01-01 19:37:22"
],
];
$lowestPrice = array_reduce(
$orders,
function($c, $v)
{
if ($c === null)
return $v["lowPrice"];
return $v["lowPrice"] < $c ? $v["lowPrice"] : $c;
}
);

Categories