PHP Array to multidimensional json data - php

I have the following php code that produces a json data set
$json_data = array(
"code"=>"200",
"name"=>"My Name",
"serial_number"=>"serial"
);
$result = json_encode($json_data);
The dataset is only one level. As I am creating this data set with a php loop. I want to be able to have multiple people but the code element be outside the users. So basically I want the json data to look like this:
{
"code": "404",
"people": [
{
"name": "Person 1",
"serial_number": "xyz"
},
{
"name": "Person Two",
"serial_number": "123"
}
]
}

Basically you want to group array of objects by property "code". There are many questions about this. Here's one of the possible methods using array_reduce.
$json_data = [
[
"code" => "200",
"name" => "My Name1",
"serial_number" => "serial1",
], [
"code" => "200",
"name" => "My Name2",
"serial_number" => "serial2",
], [
"code" => "400",
"name" => "My Name3",
"serial_number" => "serial3",
],
];
$result = array_values(array_reduce($json_data, function ($agg, $item) {
if (!isset($agg[$item['code']])) {
$agg[$item['code']] = [
"code" => $item['code'],
"people" => [],
];
}
$agg[$item['code']]['people'][] = [
"name" => $item["name"],
"serial_number" => $item["serial_number"],
];
return $agg;
}, []));
print_r($result);
Output:
Array
(
[0] => Array
(
[code] => 200
[people] => Array
(
[0] => Array
(
[name] => My Name1
[serial_number] => serial1
)
[1] => Array
(
[name] => My Name2
[serial_number] => serial2
)
)
)
[1] => Array
(
[code] => 400
[people] => Array
(
[0] => Array
(
[name] => My Name3
[serial_number] => serial3
)
)
)
)

Related

Change specific value in Dynamic nested array with parent and children structure PHP

I have a dynamic nested array structure with unique id and name, need to change value of name for a specific id given.
I have a dynamic nested array with structure
`
$array = [
[
"id" => "31350880",
"name" => "HOD",
"children" => [
[
"id" => "57f94cd7",
"parent_id" => "31350880",
"name" => "New HOD",
"children" => [
[
"id" => "e7f1c88b",
"parent_id" => "57f94cd7",
"name" => "Gold",
"children" => [
]
]
]
]
]
],
[
"id" => "45881fa8",
"name" => "Pictures",
"children" => [
[
"id" => "770e6e20",
"parent_id" => "45881fa8",
"name" => "New Picture",
"children" => [
[
"id" => "a403a8fa",
"parent_id" => "770e6e20",
"name" => "Silver",
"children" => [
]
]
]
]
]
]
];
`
For a given ID(unique) , need to find it from array and change the name from that node to a specific name.
for example : $id = ''770e6e20' which is a child of parent node with name "Pictures", need to find child node with specific id and change its name and retrieve the full array in its initial structure ?
This is a recursive function that gets a reference of your array, the id of the item and the new name to be assigned, and performs in place modification:
function modify_element_name(&$arr, $id, $name){
foreach($arr as $index => $item){
if($item['id'] === $id){
$arr[$index]['name'] = $name;
}
else {
if(count($item['children']) > 0){
modify_element_name($arr[$index]['children'], $id, $name);
}
}
}
}
Calling it as below:
modify_element_name($array, '770e6e20', 'New Picture Modified');
Will modify the array:
Array
(
[0] => Array
(
[id] => 31350880
[name] => HOD
[children] => Array
(
[0] => Array
(
[id] => 57f94cd7
[parent_id] => 31350880
[name] => New HOD
[children] => Array
(
[0] => Array
(
[id] => e7f1c88b
[parent_id] => 57f94cd7
[name] => Gold
[children] => Array
(
)
)
)
)
)
)
[1] => Array
(
[id] => 45881fa8
[name] => Pictures
[children] => Array
(
[0] => Array
(
[id] => 770e6e20
[parent_id] => 45881fa8
[name] => New Picture Modified
[children] => Array
(
[0] => Array
(
[id] => a403a8fa
[parent_id] => 770e6e20
[name] => Silver
[children] => Array
(
)
)
)
)
)
)
)

How to restructure an array so that a sub array key becomes array key

First time posting here and really need some help. Relatively new to php I have an array that I'd like to restructure. I have subjects at top level with students in a sub array. I'd like to restructure so that Students are at the top level with subjects in a sub array.
$startingArray = [
[ "subject" => "Physics",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00005", "Name" => "Jane", "email" => "jane#schooool.com",],
]
],
[ "subject" => "Chemistry",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00005", "Name" => "Jane", "email" => "jane#schooool.com",],
]
],
[ "subject" => "Mathematics",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00006", "Name" => "Fred", "email" => "fred#schooool.com",],
["id" => "00007", "Name" => "Wilma", "email" => "wilma#schooool.com",],
]
],
[ "subject" => "Biology",
"student" => [
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00006", "Name" => "Fred", "email" => "fred#schooool.com",],
["id" => "00008", "Name" => "Alison", "email" => "alison#schooool.com",],
]
]
];
I want my new array to be like this;
$endingArray = [
"students" => [
[ "id" => "00003",
"Name" => "Peter",
"email" => "peter#schooool.com",
"subjects" => [ "Physics", "Chemistry", "Mathematics", ],
],
[ "id" => "00004",
"Name" => "Mary",
"email" => "mary#schooool.com",
"subjects" => [ "Physics", "Chemistry", "Biology", ],
],
[ "id" => "00005",
"Name" => "Jane",
"email" => "jane#schooool.com",
"subjects" => [ "Physics", "Chemistry", ],
],
[ "id" => "00006",
"Name" => "Fred",
"email" => "fred#schooool.com",
"subjects" => [ "Mathematics", "Biology", ],
],
[ "id" => "00007",
"Name" => "Wilma",
"email" => "wilma#schooool.com",
"subjects" => [ "Mathematics", "Biology", ],
],
[ "id" => "00008",
"Name" => "Alison",
"email" => "alison#schooool.com",
"subjects" => [ "Physics", "Biology", ],
],
],
];
I'm trying a 2 stage process. First is to create the new students array without the subjects. This works fine.
Then I'm trying to append the subjects but I know my logic is wrong and the code I have just creates a new row for each student and each subject.
foreach ( $startingArray as $row ) {
$students = $row['student'];
foreach ($students as $student) {
if (!in_array($student, $studentsArray)) {
$studentsArray[] = $student;
}
}
}
the second step just produces garbage
$s1 = $student['id'];
foreach ($startingArray as $row) {
$subject = $row['subject'];
$students = $row['student'];
foreach ($students as $s2) {
if ($s2['id]'] = $s1) {
$student['subjects'] = $subject;
array_push($studentsArray, $student);
}
}
}
}
Any help appreciated!
Here what you can do:
$newArray = [];
foreach ($startingArray as $item) {
foreach ($item['student'] as $student) {
if (empty($newArray[$student['id']])) {
$student['subjects'] = [];
$newArray[$student['id']] = $student;
}
$newArray[$student['id']]['subjects'][] = $item['subject'];
}
}
Sample fiddle here.
Case you need to maintain a sequential id like your example do this
$newArray = [];
foreach ($startingArray as $item) {
foreach ($item["student"] as $student) {
$filter = array_filter($newArray, function ($d) use ($student) {
return ($d["id"] == $student["id"]);
});
if (!$filter) {
$student["subjects"][] = $item['subject'];
$newArray[] = $student;
} else {
$newArray[key($filter)]["subjects"][] = $item["subject"];
}
}
}
$finalArray = [
'students' => $newArray
];
The final result will be
Array
(
[students] => Array
(
[0] => Array
(
[id] => 00003
[Name] => Peter
[email] => peter#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
[2] => Mathematics
)
)
[1] => Array
(
[id] => 00004
[Name] => Mary
[email] => mary#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
[2] => Biology
)
)
[2] => Array
(
[id] => 00005
[Name] => Jane
[email] => jane#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
)
)
[3] => Array
(
[id] => 00006
[Name] => Fred
[email] => fred#schooool.com
[subjects] => Array
(
[0] => Mathematics
[1] => Biology
)
)
[4] => Array
(
[id] => 00007
[Name] => Wilma
[email] => wilma#schooool.com
[subjects] => Array
(
[0] => Mathematics
)
)
[5] => Array
(
[id] => 00008
[Name] => Alison
[email] => alison#schooool.com
[subjects] => Array
(
[0] => Biology
)
)
)
)

How to get certain values from multidimensional arrays?

Here's the data I am working with right now:
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
I would like to get a list of data associated with only "name" key.
I would also like to show the data associated with "area" key once the user go for the corresponding "name".
It would be helpful if there were any suggestion on how to better store this data for frequent usage in code.
As long as the names are unique you can do this simple trick:
Example 1
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
$names = array_column($city, null, 'name');
print_r($names);
Output
Array
(
[Dhaka] => Array
(
[name] => Dhaka
[areas] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
)
[Chittagong] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => c1
[1] => c2
[2] => c3
)
)
[Sylhet] => Array
(
[name] => Sylhet
[areas] => Array
(
[0] => s1
[1] => s2
[2] => s3
)
)
[Barisal] => Array
(
[name] => Barisal
[areas] => Array
(
[0] => b1
[1] => b2
[2] => b3
)
)
[Khulna] => Array
(
[name] => Khulna
[areas] => Array
(
[0] => k1
[1] => k2
[2] => k3
)
)
[Rajshahi] => Array
(
[name] => Rajshahi
[areas] => Array
(
[0] => r1
[1] => r2
[2] => r3
)
)
)
Now you can lookup by name
print_r($city['Chittagong']['areas']); //["c1", "c2", "c3"]
If the names are not guaranteed to be unique, you'll have to build them using foreach, like this:
Example 2
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[ /*--- ADDED to show duplication ---- */
"name" => "Chittagong",
"areas" => ["x1", "x2", "x3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
$output = [];
foreach($city as $k=>$v){
$k = $v['name'];
if(!isset($output[$k])) $output[$k] = []; //initialize
$output[$k][] = $v;
}
print_r($output);
Which will give you something like this:
Array
(
[Dhaka] => Array
(
[0] => Array
(
[name] => Dhaka
[areas] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
)
)
[Chittagong] => Array
(
[0] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => c1
[1] => c2
[2] => c3
)
)
[1] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => x1
[1] => x2
[2] => x3
)
)
)
[Sylhet] => Array( ... )
As you can see this adds an extra level in to contain the multiple occurrences. Of course you could just combine the area when duplicate (in the foreach). But that is up to you.
Here is a quick example of that (same data as above):
Example 3
$output = [];
foreach($city as $k=>$v){
$k = $v['name'];
if(!isset($output[$k])) $output[$k] = []; //initialize
$output[$k] = array_merge($output[$k], $v['areas']); //merge the areas
}
print_r($output);
Output
Array
(
[Dhaka] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
[Chittagong] => Array
(
[0] => c1
[1] => c2
[2] => c3
[3] => x1
[4] => x2
[5] => x3
)
....
)
If it was me, I would go with the last one, just because of the simplicity it will have working with it later.
PS. if your pulling data out of a Database with PDO, you can use $stmt->fetchAll(PDO::FETCH_GROUP) which will give you something like the second example automatically. The only caveat here is that the name column is the first one selected in the Query, which is the column it will group on.
Cheers.
If you're just trying to loop through the list of cities and get the names you can just use a foreach loop. If you need something beyond this try to define your question a little more.
foreach ($city as $c) {
echo $c["name"];
}

How to fetch record from an array if we have concept of array index, using array_column function?

I have an array of cryptocoin rates.
The array is looking as:
$array = Array ( [0] => Array ( [code] => BTC [name] => Bitcoin [rate] => 1 )
[1] => Array ( [code] => BCH [name] => Bitcoin Cash [rate] => 7.06364 )
[2] => Array ( [code] => USD [name] => US Dollar [rate] => 8185.84 ) )
I get results using $array[1]['rate'];
But i want to get result by [code] .
Like $array['USD']['rate']
Like $array['BCH']['rate']
How i can get the rate using currency code e.g USD
You can loop the array and build a new associative array to use in the rest of the project.
$array = Array( 0 => Array( "code" => "BTC", "name" => "Bitcoin", "rate" => 1 ),
"1" => Array ( "code" => "BCH", "name" => "Bitcoin Cash", "rate" => 7.06364 ),
"2" => Array ( "code" => "USD", "name" => "US Dollar", "rate" => 8185.84 ) );
foreach($array as $val){
$rates[$val["code"]] = $val;
}
echo $rates['USD']['rate']; // 8185.84
https://3v4l.org/0qs0n
Another option is to use array_column and array_combine to do it without loops.
$array = Array( 0 => Array( "code" => "BTC", "name" => "Bitcoin", "rate" => 1 ),
"1" => Array ( "code" => "BCH", "name" => "Bitcoin Cash", "rate" => 7.06364 ),
"2" => Array ( "code" => "USD", "name" => "US Dollar", "rate" => 8185.84 ) );
$keys = array_column($array, "code");
$rates = array_combine($keys, $array);
echo $rates['USD']['rate'];
You could use array_reduce and set the key to the value of code in the callback function:
$array = array_reduce($array, function($carry, $item) {
$carry[$item["code"]] = $item;
return $carry;
});
echo $array["USD"]["rate"]; //8185.84
Demo

mongodb pull element from multidimensional array

Hi i have the following array and i want to pull the array with productId 100343
Array(
[_id] => MongoId Object
(
[$id] => 5388a02c8ead0ebf048b4569
)
[cartId] => 14ce496ac194d5d8ee8d0cd11bd3ef5a
[products] => Array
(
[100343] => Array
(
[productId] => 100343
[quantity] => 13
[name] => a
)
[100344] => Array
(
[productId] => 100344
[quantity] => 3
[name] => ab
)
[100345] => Array
(
[productId] => 100345
[quantity] => 1
[name] => abc
)
)
)
I've tried like this but it doesn't work
$c->update(
$aQuery,
array(
'$pull' => array('products'=>array('productId'=>'100343'))
)
);
That is not an array. Arrays in MongoDB are different in concept to what PHP calls an array, so the structure you have there is the same as this JSON representation:
{
"products": {
"100343": {
"productId": 100343,
"quantity": 13,
"name": "a"
},
"100344": {
"productId": 100344,
"quantity": 3,
"name": "ab"
},
"100345": {
"productId": 100345,
"quantity": 1,
"name": "abc"
}
}
}
That sort of structure is just a use of sub-documents and is not an array in the sense as used by MongoDB. To remove the entry as you want with this structure you use the $unset operator.
$c->update(
$aQuery,
array(
'$unset' => array('products.productId.100343' => "")
)
);
But really you need to change your data, so to serialize a proper array for MongoDB you need to structure code like this:
$data = array(
"products" => array(
array(
"productId" => 100343,
"quantity" => 13,
"name" => "a"
),
array(
"productId" => 100344,
"quantity" => 3,
"name" => "ab"
),
array(
"productId" => 100345,
"quantity" => 1,
"name" => "abc"
)
)
);
That produces a JSON structure that looks like this:
{
"products":[
{
"productId":100343,
"quantity":13,
"name":"a"
},
{
"productId":100344,
"quantity":3,
"name":"ab"
},
{
"productId":100345,
"quantity":1,
"name":"abc"
}
]
}
That is what MongoDB calls an array, so now you can use the $pull operator correctly:
$c->update(
$aQuery,
array(
'$pull' => array( 'products.productId' => 100343 )
)
);

Categories