Php array transformation and combination - php

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

Related

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

PHP compare element values and push to array

I need to compare elements in array which have same elment value ex. $array[0]['change'] == $array[1]['change'] and if it true than make array push.
I have array like this
[
(int) 0 => [
'id' => (int) 2,
'uuid' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2',
'change' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2',
'company_id' => (int) 18
],
(int) 1 => [
'id' => (int) 3,
'uuid' => 'c3f388bc-9efb-4c72-b50e-3b6a9075d919',
'change' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2',
'company_id' => (int) 11
],
(int) 2 => [
'id' => (int) 4,
'uuid' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e',
'change' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e',
'company_id' => (int) 17
],
(int) 3 => [
'id' => (int) 5,
'uuid' => '52732822-11a9-4c00-8685-2493b88983f8',
'change' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e',
'company_id' => (int) 19
],
(int) 4 => [
'id' => (int) 6,
'uuid' => '9a356688-d08b-42ee-b26d-19d76bf6543b',
'change' => '9a356688-d08b-42ee-b26d-19d76bf6543b',
'company_id' => (int) 10
],
(int) 5 => [
'id' => (int) 7,
'uuid' => '8dbe1a81-d722-4261-9b13-ef0b68cbb759',
'change' => '8a356688-d08b-42ee-b26d-19d76bf6543b',
'company_id' => (int) 18
],
(int) 6 => [
'id' => (int) 8,
'uuid' => '701a896a-7d19-4cdd-80a4-f9ca7042945b',
'change' => '701a896a-7d19-4cdd-80a4-f9ca7042945b',
'company_id' => (int) 19
],
(int) 7 => [
'id' => (int) 9,
'uuid' => '64e146bf-5d76-483f-992c-274cde1202ce',
'change' => '601a896a-7d19-4cdd-80a4-f9ca7042945b',
'company_id' => (int) 20
]
]
I need to get result like this
[
(int) 0 => [
(int) 0 => [
'id' => (int) 2,
'uuid' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2',
'change' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2',
'company_id' => (int) 18
],
(int) 1 => [
'id' => (int) 3,
'uuid' => 'c3f388bc-9efb-4c72-b50e-3b6a9075d919',
'change' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2',
'company_id' => (int) 18
],
],
(int) 1 => [
(int) 0 => [
'id' => (int) 4,
'uuid' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e',
'change' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e',
'company_id' => (int) 18
],
(int) 1 => [
'id' => (int) 5,
'uuid' => '52732822-11a9-4c00-8685-2493b88983f8',
'change' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e',
'company_id' => (int) 18
],
],
(int) 2 => [
'id' => (int) 6,
'uuid' => '9a356688-d08b-42ee-b26d-19d76bf6543b',
'change' => '9a356688-d08b-42ee-b26d-19d76bf6543b',
'company_id' => (int) 18
],
(int) 3 => [
'id' => (int) 7,
'uuid' => '8dbe1a81-d722-4261-9b13-ef0b68cbb759',
'change' => '8a356688-d08b-42ee-b26d-19d76bf6543b',
'company_id' => (int) 18
],
.
.
.
]
I have tried to make 2 arrays one with same values and another with different values, than make merge but the result is not as I want... and I hope so that there is "nicer" solution (maybe more readable logic).
$exchange_array = [];
$item_array = [];
foreach ($order->items as $item) {
foreach ($order->items as $exchange) {
if (
isset($item->change) && isset($exchange->change) &&
$item->change == $exchange->change &&
$item->id != $exchange->id
) {
$exchange_array[] = $exchange;
}
if (
!isset($item->change) && !isset($exchange->change) &&
$item->id != $exchange->id
) {
$item_array[] = $exchange;
}
}
}
$item = array_merge($exchange_array,$item_array);
Thank you!
you may use foreach or array_map with this as follows :
$arrays = [
['change' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2'],
['change' => 'c876e544-eca5-4ce1-8563-ed48ac74ebc2'],
['change' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e'],
['change' => 'fa37e5a4-3b5a-4f7d-915e-4807caa5949e'],
['change' => '9a356688-d08b-42ee-b26d-19d76bf6543b'],
['change' => '8a356688-d08b-42ee-b26d-19d76bf6543b'],
['change' => '701a896a-7d19-4cdd-80a4-f9ca7042945b'],
['change' => '601a896a-7d19-4cdd-80a4-f9ca7042945b'],
];
$list = [];
foreach ($arrays as $array) {
$list[$array['change']][] = $array;
}
print_r(array_values($list));
// if you would like to use array_map instead
$list = [];
array_map(function ($array) use (&$list) {
$list[$array['change']][] = $array;
}, $arrays);
print_r(array_values($list));
live demo : https://3v4l.org/1JO58
Use the following approach:
$result = [];
foreach ($order->items as $item) {
if (isset($result[$item['change']])) {
// check if nested array is a single item(not multidimensional)
if (isset($result[$item['change']]['change'])) {
$result[$item['change']] = [$result[$item['change']], $item];
} else {
$result[$item['change']][] = $item;
}
} else {
$result[$item['change']] = $item;
}
}
$result = array_values($result);

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

Recursive count of children in nested arrays + changing values by reference

I know this is basic recursion but I get stuck anyway :(
I need to count how many elements each element has below it (children, grandchildren,...) and write that value into original array.
My example array:
$table = [
1 => [
'id' => 1,
'children_count' => 0
],
2 => [
'id' => 2,
'children_count' => 0,
'children' => [
3 => [
'id' => 3,
'children_count' => 0,
'children' => [
4 => [
'id' => 4,
'children_count' => 0,
'children' => [
5 => [
'id' => 5,
'children_count' => 0
],
6 => [
'id' => 6,
'children_count' => 0
]
]
]
]
]
]
]
];
My recursion code:
function count_children(&$array){
foreach($array['children'] as &$child){
if(isset($child['children'])){
$array['children_count'] += count_children($child);
}
else return 1;
}
}
Call for recursion:
//call for each root element
foreach($table as &$element){
if(isset($element['children'])) count_children($element);
}
Expected output:
$table = [
1 => [
'id' => 1,
'children_count' => 0
],
2 => [
'id' => 2,
'children_count' => 4,
'children' => [
3 => [
'id' => 3,
'children_count' => 3,
'children' => [
4 => [
'id' => 4,
'children_count' => 2,
'children' => [
5 => [
'id' => 5,
'children_count' => 0
],
6 => [
'id' => 6,
'children_count' => 0
]
]
]
]
]
]
]
];
Where did I got it wrong?
My function does something, element 3 gets value 1, but thats about it.
Here is the ideone link: http://ideone.com/LOnl3G
function count_children(&$table){
$count1 = 0;
foreach($table as &$array) {
$count = 0;
if (isset($array['children'])) {
$count += count($array['children']);
$count += count_children($array['children']);
}
$array['children_count'] = $count;
$count1 += $count;
}
return $count1;
}
count_children($table);
print_r($table);

Nesting an array based on parent IDs

I've been stuck trying to figure this out for a week now. I have an array in the following format:
[
1 => [
'name' => 'Maths',
'parent_category_id' => NULL
],
2 => [
'name' => 'Algebra',
'parent_category_id' => 1
],
3 => [
'name' => 'Expanding brackets',
'parent_category_id' => 2
],
4 => [
'name' => 'Factorising brackets',
'parent_category_id' => 2
],
5 => [
'name' => 'English',
'parent_category_id' => NULL
],
6 => [
'name' => 'Shakespeare',
'parent_category_id' => 5
]
]
and I want to transform it into an array in this format:
[
'Maths' => [
'category_id' => 1,
'questions' => [], //This array will then be filled with questions regarding each of the categories
'children_categories' => [
'Algebra' => [
'category_id' => 2,
'questions' => [],
'children_categories' => [
'Expanding brackets' => [
'category_id' => 3,
'questions' => [],
'children_categories' => []
],
'Factorising brackets' => [
'category_id' => 4,
'questions' => [],
'children_categories' => []
]
]
]
]
],
'English' => [
'category_id' => 5,
'questions' => [],
'children_categories' => [
'Shakespeare' => [
'category_id' => 6,
'questions' => [],
'children_categories' => []
]
]
]
]
So far I've been able to format categories that have no parents, but I for the life of me cannot figure out how to insert a category that has a parent into that parent's children_categories[] array. Here's the code I'm using, I need help figuring out what I should put in the "else" part of the foreach()
foreach($ids_as_keys as $category_id => $info){ //$info contains the name of the category, and the parent's ID (NULL if there is no parent)
if(is_null($info['parent_category_id'])){ //There is no parent, so put it at the root of $nested
$nested[$info['name']] = [
'category_id' => $category_id,
'questions' => [],
'children_categories' => []
];
}else{ //There is a parent, so search through all items (including sub-arrays, sub-sub-arrays etc.) until we find a match for the parent_category_id, and then add it into the children_categories[] array
}
}
return $nested;
I tested this, absolutely works :
$arr = array(
1 => array(
'name' => 'Maths',
'parent_category_id' => NULL
),
2 => array(
'name' => 'Algebra',
'parent_category_id' => 1
),
3 => array(
'name' => 'Expanding brackets',
'parent_category_id' => 2
),
4 => array(
'name' => 'Factorising brackets',
'parent_category_id' => 2
),
5 => array(
'name' => 'English',
'parent_category_id' => NULL
),
6 => array(
'name' => 'Shakespeare',
'parent_category_id' => 5
)
);
foreach ($arr as $key => &$value) {
if ($value['parent_category_id']) {
$arr[$value['parent_category_id']]['children_categories'][] = &$value;
}
else{
$parents[]=$key;
}
}
$result = array();
foreach ($parents as $val) {
$result[$val] = $arr[$val];
}
print_r($result);
This answer is too close may helpful for you
<?php
$array = [
1 => [
'name' => 'Maths',
'parent_category_id' => NULL
],
2 => [
'name' => 'Algebra',
'parent_category_id' => 1
],
3 => [
'name' => 'Expanding brackets',
'parent_category_id' => 2
],
4 => [
'name' => 'Factorising brackets',
'parent_category_id' => 2
],
5 => [
'name' => 'English',
'parent_category_id' => NULL
],
6 => [
'name' => 'Shakespeare',
'parent_category_id' => 5
]
];
//data array
$data = array();
$i = 0;
//gothrough one by one
foreach($array as $key=>$value)
{
//set the parent array
if(is_null($value['parent_category_id']))
{
$data[$value['name']]= array();
$data[$value['name']]['category_id'] = $key;
$data[$value['name']]['questions'] = array();
$data[$value['name']]['children_categories'] = array();
//add the childrens according to the parent
}elseif(array_key_exists($value['parent_category_id'], $array)){
//find the parent
$parent = $array[$value['parent_category_id']];
$data[$parent['name']]['children_categories'][$value['name']] = array();
$data[$parent['name']]['children_categories'][$value['name']]['category_id'] = $key;
$data[$parent['name']]['children_categories'][$value['name']]['questions'] = array();
}
}
//display the result
print_r($data);
Try using recursive function.
function insert_child($curArr,$childArray,&$parentArray){
foreach($parentArray as $key=>&$val){
if(is_array($val) && sizeof($val) > 0 ){
if($val['category_id']==$curArr['parent_category_id']){
$val['children_categories'][$curArr['name']] = $childArray;
return TRUE;
}else{
insert_child($curArr,$childArray,$val['children_categories']);
}
}
}
return FALSE;
}
Where $nest is your input array
$nest = array(
1=>array(
'name' => 'Maths',
'parent_category_id' => NULL
),
2=>array(
'name' => 'Algebra',
'parent_category_id' => 1
),
3=>array(
'name' => 'Expanding brackets',
'parent_category_id' => 2
),
4=>array(
'name' => 'Factorising brackets',
'parent_category_id' => 2
),
5=>array(
'name' => 'English',
'parent_category_id' => NULL
),
6=>array(
'name' => 'Shakespeare',
'parent_category_id' => 5
),
);
code
$result=array();
foreach($nest as $key=>$val){
$temp = array(
'category_id'=>$key,
'questions'=>array(),
'children_categories'=>array(),
);
if(!in_array($val['name'],$result) && $val['parent_category_id']==NULL){
$result[$val['name']] = $temp;
}else{
insert_child($val,$temp,$result);
}
}
echo "<pre>";
print_r($result);
exit();
PHPFIddle here

Categories