how to solve Array merge for json in this example? - php

I parse Excel sheet and get this JSON:
[
{
"A":"Samsung",
"Groupe":{
"F":"TV",
"D":"HDR"
}
},
{
"A":null,
"Groupe":{
"F":null,
"D":null
}
},
{
"A":"Sony",
"Groupe":{
"F":"T.V",
"D":"LCD"
}
},
{
"A":"Sony",
"Groupe":{
"F":"PS4",
"D":"Pro edition"
}
},
{
"A":"Sony",
"Groupe":{
"F":"Smart Phone",
"D":"Quad core"
}
}
]
Php code:
$data = [];
for ($row = 15; $row <= 25; $row++) {
$data[] = [
'A' => $worksheet->getCell('A'.$row)->getValue(),
'Groupe' => [
'F' => $worksheet->getCell('F'.$row)->getValue(),
'D' => $worksheet->getCell('D'.$row)->getValue()
]
];
}
How can I organize(sort) json depending on "A"?
I tried this but I still couldn't merge "Groupe" for same "A" together:
Take away NULL colomns.
Create a copy of the Array.
Regroup fields for same element in the new Array(this didnt work)
Code:
$data1 = [];
for ($l = 0; $l < count($data); $l++){
$data1[$l] = $data[$l];
}
for ($j = 0; $j < count($data); $j++) {
if($data[$j]['A'] != NULL){
if($data[$j]['A'] !== $data[$j+1]['A']){
$data1[$j] = $data[$j];
}
else{
$data1[$j]['A']= $data[$j]['A'];
$data1[$j]['Groupe']= array_merge($data[$j]['Groupe'], $data[$j+1]['Groupe']);
}
}
}
EDIT:
The result that I'm getting for $data1 is exactly the same as the input JSON(except that NULL was deleted), so it looks like merge Array didnt work and what I need is:
[
{
"A":"Samsung",
"Groupe":{
"F":"TV",
"D":"HDR"
}
},
{
"A":"Sony",
"Groupe": [{
"F":"T.V",
"D":"LCD"
},{
"F":"PS4",
"D":"Pro edition"
}, {"F":"Smart Phone",
"D":"Quad core"
}]
}]
Plus it's showing me this :
Notice: Undefined offset: 11 in C:\xampp\htdocs\phptoexcel.php on line
43
Line 43: if($data[$j]['A'] !== $data[$j+1]['A']){

Use the A value as key in $data, so you can group by it:
$data = [];
for ($row = 15; $row <= 25; $row++) {
//get A value, skip if A = NULL
$a = $worksheet->getCell('A'.$row)->getValue(),
if($a===NULL)continue;
//get F and D VALUE, skip if one of them = NULL
$f = $worksheet->getCell('F'.$row)->getValue();
$d = $worksheet->getCell('D'.$row)->getValue();
if($f===null || $d===null)continue;
//test if A is a key in $data. If not, create
if(!array_key_exist( $a, $data ){
$data[$a]=[
'A'=>$a,
'Groupe'=>[]
];
}
//Put F and D in a new array in Groupe
$data[$a]['Groupe'][]=["F"=>$f,"D"=>$d];
}
You will end up with:
$data=>
[ "Samsung" =>[ "A" => "Samsung",
"Groupe" => [ 0 =>[ "F" => "TV",
"D" => "HDR"
]
]
],
"Sony" => [ "A" => "Sony",
"Groupe" => [ 0 =>[ "F":"TV",
"D":"HDR"
],
1 =>[ "F":"T.V",
"D":"LCD"
],
2 =>[ "F":"PS4",
"D":"Pro edition"
],
3 =>[ "F":"Smart Phone",
"D":"Quad core"
],
]
]

Try This
$arrUnique = array();
$result = array();
$i=0;
foreach($data as $value){
if($value['A']!=null){
$data1 = [];
$intID = $value['A'];
if( in_array( $intID, $arrUnique ) ) {
$key = array_search ($intID, $arrUnique);
$result[$key]['Groupe'][] = $value['Groupe'];
}else{
$data1['A'] = $value['A'];
$data1['Groupe'][] = $value['Groupe'];
$result[$i]=$data1;
$arrUnique[]=$value['A'];
$i++;
}
}
}

I usually don't perform JSON to JSON transformation using PHP but using jq command line utility.
Given your input JSON file, you can use this jq filter:
jq '[[sort_by(.A)|.[]|select(.A!=null)]|group_by(.A)|.[]as $i|{A:$i[].A,Groupe:$i|map(.Groupe)}]|unique' file
[
{
"A": "Samsung",
"Groupe": [
{
"F": "TV",
"D": "HDR"
}
]
},
{
"A": "Sony",
"Groupe": [
{
"F": "T.V",
"D": "LCD"
},
{
"F": "PS4",
"D": "Pro edition"
},
{
"F": "Smart Phone",
"D": "Quad core"
}
]
}
]

Related

codeigniter create response array object

I have the code below, but the result of the json response doesn't match
public function tes_get(){
$kode= $this->M_mymodel->tbl_kode('302'); // row
$res = array();
foreach ($kode as $key=> $value) {
$win = $this->M_mymodel->db_aa('302'); //row_array
$res = $this->M_mymodel->db_bb('302','LOSE'); //row_array
$res['data'][] = array(
'win' => $win['menang'],
'lose' =>$res['kalah']
);
}
$response = $this->set_response($res,200);
}
Below is the result of the response from the code I made above
{
"data": [
{
"win": "2",
"lose": "11"
}
]
}
How to make json response like below?
{
"data": [
{
"win": "2",
}
{
"lose": "11"
}
]
}
You can try :
$res['data'][] = array(
array('win' => $win['menang']),
array('lose' =>$res['kalah'])
);

get parent nodes from a node tree array

[
{
"id": 1573695284631,
"name": "Cars",
"pid": 0,
"children": [
{
"id": 1573695292010,
"name": "Audi",
"pid": 1573695284631
},
{
"id": 1573695305619,
"name": "BMW",
"pid": 1573695284631,
"children": [
{
"id": 1573695328137,
"name": "3 Series",
"pid": 1573695305619
},
{
"id": 1573695335102,
"name": "X5",
"pid": 1573695305619
}
]
}
]
},
{
"id": 1573695348647,
"name": "Motorcycles",
"pid": 0,
"children": [
{
"id": 1573695355619,
"name": "Ducatti",
"pid": 1573695348647
}
]
}
]
Suppose I have this node-tree-like array in PHP (represented above in json for readability). For a given child node ID, I would like to find all parent node IDs that it's nested under. For example,
getParentNodes($haystack, $child_node_id=1573695328137); //[1573695284631, 1573695292010, 1573695305619]
I assume this is a use case for recursion. Here's my best attempt:
function getParentNodes($haystack, $child_node_id) {
if( empty($haystack->children) )
return;
foreach($haystack->children as $child) {
if($child->id == $child_node_id) {
// $child found, now recursively get parents
} else {
getParentNodes($child, $child_node_id);
}
}
}
This one will walk the tree until it hits the desired id.
In all cases where the leaf is not the desired one, it will return false - and collapse up the stack resulting in false or an array of parent-ids if the child is found.
Code
function getParentNodes($haystack, $child_node_id) {
foreach ($haystack as $element) {
if ($element['id'] === $child_node_id) {
// return [$element['id']]; // uncomment if you want to include child itself
return [];
} else if (array_key_exists('children', $element)) {
$parentNodes = getParentNodes($element['children'], $child_node_id);
if ($parentNodes !== false) {
return [$element['id'], ...$parentNodes];
}
}
}
return false;
}
Outputs parent ids:
array(2) {
[0]=>
int(1573695284631)
[1]=>
int(1573695305619)
}
Working example.
You missing return result. This is what you want.
function getParentNodes($arr, $child_node_id) {
$result = [];
foreach($arr as $item) {
if($item->pid == $child_node_id) {
$result[] = $item->id;
}
if(!empty($item->children)) {
$result[] = getParentNodes($item->children, $child_node_id);
}
}
return $result;
}
also you need get values as flat array
$values = getParentNodes($values, 1573695284631);
// do flat arr
array_walk_recursive($values,function($v) use (&$result){ $result[] = $v; });
// your values
var_dump($result);
Source reference for flat array
I ended up writing 2 recursive functions
function treeSearch($needle, $haystack) {
foreach($haystack as $node) {
if($node->id == $needle) {
return $node;
} elseif ( isset($node->children) ) {
$result = treeSearch($needle, $node->children);
if ($result !== false){
return $result;
}
}
}
return false;
}
treeSearch will find the node in the tree, then I need to recursively go up the tree until the parent id (pid) is 0
function getParents($node, $hierarchy, $all_parent_ids=[]) {
if($node->pid != 0) {
$parent_node = treeSearch($node->pid, $hierarchy);
$all_parent_ids[] = $parent_node->id;
$result = getParents($parent_node, $hierarchy, $all_parent_ids);
if ($result !== false){
return $result;
}
}
return $all_parent_ids;
}
then, supposing the tree is called $tree I can call them like:
$node = treeSearch(1573695328137, $tree);
$parents = getParents($node, $tree);
This is the best solution to take the parent of a child !
function getPathParent($id, $tree='',$opts='', &$path = array()) {
$in = array_replace(array(
'id'=>'id',
'child'=>'children',
'return'=>'id'
),(array)$opts);
if ( is_array($tree) && !empty($tree) ){
foreach ($tree as $item) {
if ($item[$in['id']] == $id) {
array_push($path, $item[$in['return']]);
return $path;
}
if ( isset($item[$in['child']]) && !empty($item[$in['child']]) ) {
array_push($path, $item[$in['return']]);
if (getPathParent($id, $item[$in['child']],$opts, $path) === false) {
array_pop($path);
} else {
return $path;
}
}
}
}
return false;
}
$tree = [
[
"id" => 1573695284631,
"name" => "Cars",
"pid" => 0,
"children" => [
[
"id" => 1573695292010,
"name" => "Audi",
"pid" => 1573695284631
],
[
"id" => 1573695305619,
"name" => "BMW",
"pid" => 1573695284631,
"children" => [
[
"id" => 1573695328137,
"name" => "3 Series",
"pid" => 1573695305619
],
[
"id" => 1573695335102,
"name" => "X5",
"pid" => 1573695305619
]
]
]
]
],
[
"id" => 1573695348647,
"name" => "Motorcycles",
"pid" => 0,
"children" => [
[
"id" => 1573695355619,
"name" => "Ducatti",
"pid" => 1573695348647
]
]
]
];
$getParentNode = getPathParent(1573695335102,$tree);
var_export($getParentNode);
// return:
/*
array (
0 => 1573695284631,
1 => 1573695305619,
2 => 1573695335102,
)
*/
$getParentNode = getPathParent(1573695335102,$tree,array('return'=>'name'));
var_export($getParentNode);
// return:
/*
array (
0 => 'Cars',
1 => 'BMW',
2 => 'X5',
)
*/
$getParentNode = getPathParent(1573695335102,$tree,array('id'=>'id','child'=>'children','return'=>'pid'));
var_export($getParentNode);
// return:
/*
array (
0 => 0,
1 => 1573695284631,
2 => 1573695305619,
)
*/

How to change json array format in php?

I have php script which is storing data into an array and then converting into json array. Following is script
$gameTraining = array();
$index = 0;
foreach($todayTraining->toArray() as $training){
if($todayTraining[$index]['type'] === 'easy'){
$gameTraining['easy'][]['game_id'] = $todayTraining[$index]['game_id'];
}
$index++;
}
return $gameTraining;
And following response I am getting
{
"training": {
"easy": [
{
"game_id": 12
},
{
"game_id": 6
},
{
"game_id": 26
}
]
}
}
But I would like to remove the brackets from array, so can you kindly guide me how can I do that? I would like to convert as following
{
"training": {
"easy": [
"game_id": 12,
"game_id": 6,
"game_id": 26
]
}
}
You cannot have multiple items in an array with the same key. You can make an array with the ids for the game, so this line:
$gameTraining['easy'][]['game_id'] = $todayTraining[$index]['game_id'];
can be changed with this line:
$gameTraining['easy']['game_ids'][] = $todayTraining[$index]['game_id'];
Try something like this:
$todayTraining = [
[
'type' => 'easy',
'game_id' => 123
],
[
'type' => 'easy',
'game_id' => 456
]
];
$gameTraining = array();
$index = 0;
foreach($todayTraining as $training){
if($todayTraining[$index]['type'] === 'easy'){
$gameTraining['easy'][] = substr(json_encode(['game_id' => $todayTraining[$index]['game_id']]), 1, -1);
}
$index++;
}
echo json_encode($gameTraining, JSON_PRETTY_PRINT);
Just use below line :
$gameTraining['easy'][] = $todayTraining[$index]['game_id'];
Instead of :
$gameTraining['easy'][]['game_id'] = $todayTraining[$index]['game_id'];
Hopefully, it will work.

Add another key php array json

Please correct the terminologies that I am using.
I am trying to return a json data like this:
"data": [
{
"id": 1
"name": "test"
},
{
{
"id": 2
"name": "abc"
},
{
"id": 3
"name": "zxc"
}
]
and my code is exactly this one
$data = [];
foreach($prices as $price) {
$data[]["id"] = $price->id;
$data[]["name"] = $price->name;
}
$result["data"] = $data;
the code returns the json like this:
"data": [
{
"id": 1
},
{
"name": "test"
}
{
"id": 2
},
{
"name": "abc"
}
{
"id": 3
},
{
"name": "zxc"
}
]
Sorry for the bad formatting.
Like this
foreach($prices as $price) {
$data[] = [
"id"=> $price->id,
"name" => $price->name
];
}
You are adding the items sequentially, when you need to group them in an array and then add that array as a single unit.
$i = 0;
$data = [];
foreach($prices as $price) {
$data[$i]["id"] = $price->id;
$data[$i]["name"] = $price->name;
$i++;
}
$result["data"] = $data;
The problem is that you keep appending to the array instead of appending to an object and then to the $data array.
Try like this
$data = [];
foreach($prices as $price) {
$topush = [];
$topush["id"] = $price->id;
$topush["name"] = $price->name;
$data[] = $toReturn;
}
$result["data"] = $data;
or, even shorter
$data = [];
foreach($prices as $price) {
$data[] = ['id' => $price->id, 'name' => $price->name];
}
$result["data"] = $data;
You are adding two new Elements to your output, one containing the key/value for id and the other one for name. You have to put both into one element:
$data[]["id"] = $price->id; // Add one element
$data[]["name"] = $price->name; // Add second element
// New
$data[] = ['id' => $price->id, 'name' => $price->name]; // Add both as one Element
Empty [] creates new index every time. You must specify index where you wish to insert:
$data = [];
foreach($prices as $i => $price) {
$data[$i]["id"] = $price->id;
$data[$i]["name"] = $price->name;
}
$result["data"] = $data;
You kept assigning the value to a new key you should assign the data you want bundle in one go.
$data = [];
foreach($prices as $price) {
$data[] = [
"id" => $price->id,
"name" => $price->name;
]
}
$result["data"] = $data;

Recursivly search array and sum field

I am trying to write a recursive function that will iterate over an array of arrays and sum a specific field. Here is an example of an array:
{
"68": {
"10": [
{
"id": "3333",
"sumTHis": "5"
}
]
},
"69": {
"45": [
{
"id": "3333",
"sumTHis": "5"
}
],
"50": [
{
"id": "3330",
"sumTHis": "5"
},
{
"id": "3331",
"sumTHis": "5"
},
{
"id": "3332",
"sumTHis": "5"
},
{
"id": "3333",
"sumTHis": "5"
}
]
}
}
The problem is that the array could be any number of sub-arrays deep. In the end, I would like to be able to sum all "sumTHis" nodes throughout the entire array The code I have so far is this:
//in body
$sumThis= recurse_get_total($array, 'sumTHis');
//recursive function
function recurse_get_total($report_data, $valId, $total = 0){
try{
foreach ($report_data as $key => $value) {
if(is_array_of_arrays($value)){
recurse_get_total($value, $valId, $total);
}else{
$total = $total + $value[$valId];
return $total;
}
}
return $total;
}catch(Exception $err){
throw $err;
}
}
function is_array_of_arrays($isArray){
try{
if(is_array($isArray)){
foreach($isArray as $key => $value){
if(!is_array($value)){
return false;
}
}
return true;
}
}catch(Exception $err){
throw $err;
}
}
This function starts to iterate over the array but gets kicked out after the first one and returns 0. Can anyone help out?
Thanks
jason
Going about this problem I set something up with "array_walk_recursive". Seeing that you want to add some stuff independent of the depth of the arrays, this seems to work.
It is not solving it with what you have, but perhaps this different approach will get you there.
$sum = 0;
$array = array(
"one" => array(
"day" => "tuesday",
"week" => "20",
"findthis" => 10
),
"two" => array("subone" => array(
"some" => "one",
"findthis" => 23
)),
"deeperthree" => array("subtwo" => array("deeper" => array(
"one" => "entry",
"findthis" => 44
)))
);
function callback($val, $key, $arg) {
if ($key == "findthis") {
$arg[0]($val, $arg[1]);
}
};
$function = function($num, &$sum) {
$sum = $sum + $num;
echo $sum . " ";
};
array_walk_recursive($array, "callback", array( $function, &$sum ));
result: 10 33 77

Categories