I have two arrays one is $apiRes and second is $mappData i want to match fields exist in mappData array and assign value of apiRes to match field.
Note: response of api may have different and mapdata array will change according to api response My two array and output format :
<?php
$apiRes = [
[
'firstname' => 'first name des',
'title' => "title des",
'category' => 1,
'result' =>
[
0 => [
'name' => 'Masterpass',
'skill' => 'low level one'
],
1 => [
'name' => 'Visa',
'skill' => 'low level two'
],
2 => [
'name' => 'Pocketpos',
'skill' => 'low level three'
],
],
'list' => [
'product_name'=>'product name',
'amount' => [
'currency'=>'$',
'kind' => 'kind'
]
],
'priority' => 'Low',
'visible_to' => 'Everyone',
]
];
$mappData = [
0 => [
"src_field" => "firstname",
"target_field" => "new1519110449758",
"src_field_data_type" => "string"
],
1 => [
"src_field" => "result.name",
"target_field" => "new1519110811942",
"src_field_data_type" => "string"
],
2 => [
"src_field" => "list.product_name",
"target_field" => "new1519110451708",
"src_field_data_type" => "string"
],
3 => [
"src_field" => "list.amount.currency",
"target_field" => "new1517556165360",
"src_field_data_type" => "string"
]
];
My final output should be:
$output = [
"new1519110449758" => "first name des",
"new1519110451708" => "product name",
"new1517556165360" => "$",
"new1519110811942" => [
0 => "Masterpass",
1 => "Visa",
2 => "Pocketpos"
]
];
Please help
Thanks
I've changed your mappData slightly as it's difficult to know how to deal with the result.name element as it's repeated. What I've done is change it so that it's *result.name and it uses the fact there is an * in it to mean there are multiple values.
I've tried to comment the code with enough to explain each bit, the main principle is using a recursive routine to go through each level of the array one step at a time.
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);
$apiRes = [
[
'firstname' => 'first name des',
'title' => "title des",
'category' => 1,
'result' =>
[
0 => [
'name' => 'Masterpass',
'skill' => 'low level one'
],
1 => [
'name' => 'Visa',
'skill' => 'low level two'
],
2 => [
'name' => 'Pocketpos',
'skill' => 'low level three'
],
],
'list' => [
'product_name'=>'product name',
'amount' => [
'currency'=>'$',
'kind' => 'kind'
]
],
'priority' => 'Low',
'visible_to' => 'Everyone',
]
];
$mappData = [
0 => [
"src_field" => "firstname",
"target_field" => "new1519110449758",
"src_field_data_type" => "string"
]
,
1 => [
"src_field" => "*result.name",
"target_field" => "new1519110811942",
"src_field_data_type" => "string"
],
2 => [
"src_field" => "list.product_name",
"target_field" => "new1519110451708",
"src_field_data_type" => "string"
],
3 => [
"src_field" => "list.amount.currency",
"target_field" => "new1517556165360",
"src_field_data_type" => "string"
]
];
$result = [];
// Process next element of the array
function getArrayElement ( $next, $data, $array = false ) {
// Extract key for this level
$key = array_shift($next);
// If starts with * then this means there are multiple of them
if ( $key[0] == "*" ){
$nextArray = true;
// remove from current key
$key = substr($key,1);
}
else {
$nextArray = false;
}
if ( $array ){
$res = [];
// extract the data from each element at this level
foreach ( $data as $read ) {
$res[] = $read[$key];
}
$data = $res;
}
else {
// Fetch the element for the key for this level
$data = $data [ $key ];
}
// If there are more levels to deal with then repeat this method
if ( count($next) > 0 ) {
$data = getArrayElement ( $next, $data, $nextArray );
}
return $data;
}
// Flatten out original array if necessary
if ( count($apiRes) == 1 ){
$apiRes = $apiRes[0];
}
// Process each part of lookup
foreach ( $mappData as $element ) {
// Create an array of the elments broken down into each level
$map = explode( '.', $element['src_field']);
$result[$element['target_field']] = getArrayElement($map, $apiRes);
}
print_r($result);
Related
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
)
)
Is it possible to search a multidimensional array of unknown depth by value?
For example, with:
$data = [
[
'uid' => '100',
'name' => 'MAIN',
[
'uid' => '2222',
'name' => 'SUB_MAIN',
[
'uid' => '8524',
'name' => 'SUB_SUB_MAIN',
]
]
],
[
'uid' => '5465',
'name' => 'MAIN',
],
[
'uid' => '40489',
'name' => 'MAIN',
]
];
I want to find the path to the sub-array where uid is 8524.
With the above array, the result should be: [0, 0, 0].
You can use the following as a starting point:
<?php
declare(strict_types=1);
error_reporting(-1);
ini_set('display_errors', 'On');
function findPath(array $items, callable $criteria, array $path = []): array {
foreach ($items as $key => $item) {
if (!is_array($item)) {
continue;
}
// prepare path to this item
$pathToHere = array_merge($path, [$key]);
// if the items fits the criteria
if ($criteria($item)) {
// return it's path
return $pathToHere;
}
// otherwise check children
$pathToChild = findPath($item, $criteria, $pathToHere);
// and if return value is not empty
if (count($pathToChild) > 0) {
// return path to child
return $pathToChild;
}
}
// base case if no item matches
return [];
}
$data = [
[
'uid' => '5465',
'name' => 'MAIN',
],
[
'uid' => '100',
'name' => 'MAIN',
[
'uid' => '2222',
'name' => 'SUB_MAIN',
[
'uid' => '8524',
'name' => 'SUB_SUB_MAIN',
[
'uid' => 'X',
'name' => 'Y',
]
],
[
'uid' => '8524_test',
'name' => 'SUB_SUB_MAIN_test',
[
'uid' => '8524_test_sub',
'name' => 'SUB_SUB_MAIN_test_sub',
]
]
]
],
[
'uid' => '40489',
'name' => 'MAIN',
]
];
$path = findPath($data, fn(array $item): bool => $item['uid'] === '8524_test_sub');
print_r($path);
/*
Array
(
[0] => 1
[1] => 0
[2] => 1
[3] => 0
)
*/
Demo: https://3v4l.org/XKTH8
Note the code above requires php 7.4, but only because of the fn() => ... construct. This could simply be replaced by any other suitable callable.
How to get particular nested array based on the given matched key using PHP built in function
Scenario
$id = 1035; // Searching ID
$a = [
'id'=> 291,
'children' => [
[
'id' => 1034,
'children' => [
[
'id' => 111,
'name' => 'ABC',
'figure' => '6 digits',
'children'=> []
],
[
'id' => 1035,
'lft' => 'LEFT',
'children' => [
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
]
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
],
]
],
],
[
'id' => 1024,
'title' => 'ABC',
'children' => [
],
]
]
];
Please note, 'id' & 'children' keys are always be there. How to get the "children" of "1035" ID..?
Expected Output
[
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
],
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
];
Tried
function getRecursiveCategoryIds($key, $categories = []){
$return = null;
try {
array_walk_recursive($categories, function($v, $k) use ($key, &$return){
if (null != $return) {
// Run loop to get the next immediate "children" key
if ($k == 'children') { // It's not matching anymore
$return = $v;
//return false;
throw new Exception;
}
} else if($v == $key) {
// Found
$return = $v;
}
});
} catch(Exception $e) {}
return $return;
}
$d = getRecursiveCategoryIds($id, $a);
echo '<pre>D: '; print_r($d); die;
I tried by the above code, but the "if ($k == 'children') {" is not matched any more..!
Any suggestions are welcome... (PHP's Built in function is most prefer!)
I was able to do this. Please check the comments in the code:
<?php
$id = 1035; // Searching ID
$myObj = array();
$a = [
'id'=> 291,
'children' => [
[
'id' => 1034,
'children' => [
[
'id' => 111,
'name' => 'ABC',
'figure' => '6 digits',
'children'=> []
],
[
'id' => 1035,
'lft' => 'LEFT',
'children' => [
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
]
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
],
]
],
],
[
'id' => 1024,
'title' => 'ABC',
'children' => [
],
]
]
];
function findObject($id, $obj) {
global $myObj;
// This is an object.
if (isset($obj["id"])) {
echo "Checking {$obj["id"]}<br />";
// Check the id to what we need.
if ($obj["id"] == $id) {
// Yay! We found it. Return the object.
echo "Yay we found {$obj["id"]}<br />";
$myObj = $obj;
}
else {
echo "Checking children of {$obj["id"]}<br />";
// See if it has any children
if (isset($obj["children"]) && count($obj["children"]) > 0) {
echo "There are children for {$obj["id"]}<br />";
foreach ($obj["children"] as $child) {
findObject($id, $child);
}
}
}
}
}
findObject($id, $a);
print_r($myObj);
Output
Checking 291Checking children of 291There are children for 291Checking 1034Checking children of 1034There are children for 1034Checking 111Checking children of 111Checking 1035Yay we found 1035Need to find a way to break out!Checking 1024Checking children of 1024Found it!Array
(
[id] => 1035
[lft] => LEFT
[children] => Array
(
[0] => Array
(
[id] => 1036
[children] => Array
(
[0] => Array
(
[id] => 222
[someKey] => some value
[children] => Array
(
)
)
)
)
[1] => Array
(
[id] => 333
[someKey] => some value
[children] => Array
(
)
)
)
)
Demo:
https://ideone.com/UoKqrU
https://3v4l.org/rWkPq
You can use function inside other check :
$id=1035;
$a = [
'id'=> 291,
'children' => [
[
'id' => 1034,
'children' => [
[
'id' => 111,
'name' => 'ABC',
'figure' => '6 digits',
'children'=> []
],
[
'id' => 1035,
'lft' => 'LEFT',
'children' => [
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
]
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
],
]
],
],
[
'id' => 1024,
'title' => 'ABC',
'children' => [
],
]
]
];
function nigsearch($arr,$id)
{
if(gettype($arr) == 'array')
foreach($arr as $key =>$list)
{
if(gettype($list) == 'array'){
if(isset($list['id']))
{
if($list['id'] ==$id)
print_r($list['children']);
}
nigsearch($list,$id);
}
}
}
foreach($a as $key)
{
nigsearch($key,$id);
}
I am trying to make a multi-dimensional array build an array path adding the hr field so it looks like this:
I just can't figure out how to add the totals, nor create a sub-array so the dot notation in an option too. My goal is to get something like this:
[1] => [1][2][1][5][0][6] = 35 (the second child path "1")
[1] => [1][2][1][5][0][7] = 25
or Something like this:
array (
[children.0.children.0.children.0.total] = 20
[children.0.children.1.children.1.total] = 35
// etc
)
The complicated part is that it goes in different directions and I want to know what is the highest and lowest total based on the path:
==> Run Code Here or Copy/Paste
// -------------
// The Flattener
// -------------
function doit($myArray) {
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($myArray));
$result = array();
foreach ($iter as $leafKey => $leafValue) {
$keys = array();
foreach (range(0, $iter->getDepth()) as $depth) {
$keys[] = $iter->getSubIterator($depth)->key();
}
$result[ join('.', $keys) ] = $leafValue;
}
return $result;
}
// -------------
// Example Tree
// -------------
$tree = [
'id' => 1,
'type' => 'note',
'data' => [],
'children' => [
[
'id' => 2,
'type' => 'wait',
'data' => [
'hr' => 10,
],
'children' => [
[
'id' => 3,
'type' => 'wait',
'data' => [
'hr' => 10,
],
'children' => [
'id' => 4,
'type' => 'exit',
'data' => [],
'children' => []
]
],
[
'id' => 5,
'type' => 'note',
'data' => [
'hr' => 10,
],
'children' => [
[
'id' => 6,
'type' => 'wait',
'data' => [
'hr' => 10,
],
'children' => []
],
[
'id' => 7,
'type' => 'exit',
'data' => [],
'children' => []
],
]
]
],
]
]
];
$result = doit($tree);
print_r($result);
This seems to work, I found it somewhere googling all day.
array_reduce(array_reverse($keys), function($parent_array, $key) {
return $parent_array ? [$key => $parent_array] : [$key];
}, null);
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