How to create json from array in php like APIs - php

I have a sample 2018 student pass record of CSV file like this...
1 | Jonathan | 4CS-10 | 1,2,3,4 | Pass with credit
2 | Peter Jo | 4CS-11 | 1,2,3,4 | Pass with credit
and I want to convert it into Json. So firstly I thought I need to change it into php array and then i have to use json_encode function.
I have fetched CSV data into array with fgetcsv().
The final json result I want to achieve is the following:
{"2018" : {
"4CS-10" : {
"name" : "Jonathan",
"destinations": "1,2,3,4"
},
"4CS-11" : {
"name" : "Peter Joe",
"destinations": "1,2,3,4"
}
}
}

To produce that structure you need to iterate your CSV array and transform the rows to associative arrays, then add each row to your output array using the second column as a key.
foreach ($your_array as $row) {
// ↓ use 4CS-10, etc. as keys
$data[$row[2]] = ['name' => $row[1], 'destinations' => $row[3]];
// convert numeric keys ↑ to string keys ↑
}
echo json_encode(['2018' => $data]);
You may have trouble with this if the column you're using as key (values like 4CS-10, etc.) is not unique. If any values there are repeated, you'll only get the last row from the CSV because you'll overwrite the original value of that key. If that's the case, you'll need to change your structure a little if you want to get all the data, and make the value under 4CS-10 an array of objects instead of a single object.
$data[$row[2]][] = ['name' => $row[1], 'destinations' => $row[3]];

Related

Restructure 2d array so that column values become row values (transpose but preserve first level keys)

The situation is as follows. I have a parent array which looks like the following:
$parent = [
1 => ['test1', 'test2'],
2 => ['test1_1', 'test2_2'],
];
I would like to group the data by column.
Desired result:
[
1 => ['test1', 'test1_1'],
2 => ['test2', 'test2_2'],
]
1 parent array called parent contains 2 arrays inside. I want to combine these two so that they have the same values as stated above. So this would mean that the arrays should be combined based on index number.
Since I do not make use of string keys, how would I accomplish this? I believe that there is no build in function available for this situation.
I would imagine that I could start beginning to create a new array and use a for loop through the parent array.
I tried the array-combine function however, this is NOT displaying the results I want.
[
1 => ['test1' => 'test1_1', 'test2' => 'test2_2'
]
If you need to preserve those first level keys, you can re-apply them after tranposing.
Code: (Demo)
var_export(
array_combine(array_keys($parent), array_map(null, ...$parent))
);
Otherwise, you can just transpose and accept the re-indexed first level keys. Honestly, I can't see any good reason to preserve the first level keys because by transposing, you remove the initial association between first level keys and the row values.
Code: (Demo)
var_export(
array_map(null, ...$parent)
);
If these techniques do not suit your actual project data, then we will need a more realistic sample array to be provided in your question body.
Loop over the keys of the top-level array. Then use the current index of the iteration to get the corresponding columns of the nested arrays.
$result = [];
foreach (array_keys($parent) as $i => $k) {
$result[$k] = array_column($parent, $i);
}
DEMO
This assumes the number of rows is the same as the number of columns. It's not clear what you expect the result to be if that's not true.

JSON/PHP issue, cannot echo the value but it's present

I have a small issue. I have a json file which I fetch data from.
When I print_r() the data, I see the field I want. But trying to call them, only 2 on 3 works, one seems to not be fetch-able.
Here the code, if someone have an idea about what's wrong:
Original JSON :
[
{
"ņame": "Xcoin",
"rate": "100.0000",
"status": "online"
}
]
The JSON with print_r()
Array
(
[ņame] => XCoin
[rate] => 100.0000
[status] => online
)
When I fetch individually each fields:
echo $coin['name']."<br>";
echo $coin['rate']."<br>";
echo $coin['status']."<br>";
The result of the previous code:
100.0000
online
Like if the name was not there! How's possible? I have others array and name fetch correctly, using same format.
Look at your array keys: ņ !== n so you're referencing an array index that doesn't exist.
I.e., that is not an n in the JSON you're getting, it's one of these characters.
(TIL this thing is called a cedilla.)
Look it's other character
ņame != name

PHP MySQL one-to-many database return removing duplicate entries when outputting to a HTML table

I'm returning an array much like the simplified example below:
0 =>
object(stdClass)[9]
public 'crew_chief' => string 'Alan' (length=4)
public 'location' => string '1a' (length=2)
1 =>
object(stdClass)[22]
public 'crew_chief' => string 'Alan' (length=4)
public 'location' => string '2a' (length=2)
I would like my loop over my array and remove certain duplicate info (in this case "Alan")
Desired output would look like the below in a HTML table row <tr>:
Alan
1a
2a
I have tried:
foreach($records as $r) {
<tr>
<td>
$r->crew_chief;
</td>
<td>
$r->location . <br />;
</td>
</tr>
}
The best way to do this is from the MySQL query directly by using the statement SELECT DISTINCT col FROM table WHERE data='data' GROUP BY row
However if you want to use your code you would be able to do this with storing each name in a separate array array['Alan'] = 'data' and reloop over this array to output the data, cause the index Alan already exists and gets overwritten.
Whenever you'd like to eliminate duplicate entries in an array, you can simply loop through the array, placing each element into a new array which uses the value of the duplicated index as the new array's index. This way, duplicates are naturally eliminated as they just overwrite each other.
Take this, for example. This takes into account that you have an array of objects, but the concept is the same for an array of arrays as well.
$condensed = array();
foreach( $records as $index=>$r ) {
$condensed[$r->crew_chief] = $r;
// optionally, you can save the original index, so that you can rebuild
// the original array with the same original index structure again
$condensed[$r->crew_chief]['original_index'] = $index;
}
// that eliminated all the duplicates, but if you want your array to
// have the same structure (with same indexes) as the original, let's
// use our saved indexes above to rebuild things as they were
$deduped = array();
foreach( $condensed as $c ) {
$deduped[$c['original_index']] = $c;
unset($deduped[$c['original_index']]['original_index']); // be clean!
}
// don't forget memory management
unset($condensed);

PHP JSON Count values in same array

I have a json object in my php script that was encoded using the json_encode php function.
Here is the object when var_dumped...
string '{"voting_sys":"50","beta_site":"50"}' (length=36)
string '{"voting_sys":"50","beta_site":"50"}' (length=36)
Database structure:
My goal is to get the sum of the values in the voting_sys for each user, and in the beta_site...this is going to be used for voting, but on an unknown amount of features/values.
Any ideas? I have tried the following...
$voters = DB::table('votes')->get();
foreach($voters as $vote){
$vote_array[$voter->user_id]=json_decode($voter->value, true);
}
var_dump($vote_array);
This returns the decoded json object to the array.
I would assign the "voting_sys" as the key for the array, and then the integer value to the value of the array, but there will be an unknown number of features. In this example, there are only two features the users can vote on, but there may be more at a later date. I use the feature ID to roll out a new set of features the users can vote on.
I am using Laravel 4.1
[Edit: Result]
$feature_list = DB::table('features')->where('rev_id', Config::get('app.beta_rev'))->get();
$feature_array=array();
foreach ($feature_list as $feature){
array_push($feature_array, $feature->name);
}
foreach($feature_array as $feature){
$voters = DB::table('votes')
->select(DB::raw('sum(value)'))
->where('feature_name', '=', $feature)
->get();
echo $feature.' - ';
var_dump($voters);
echo '<br />';
}
which when called, dumps:
voting_sys -
array (size=1)
0 =>
object(stdClass)[248]
public 'sum(value)' => string '149' (length=3)
beta_site -
array (size=1)
0 =>
object(stdClass)[249]
public 'sum(value)' => string '69' (length=2)
Which is exactly correct for the votes I entered. Thanks for the help.
I would suggest using a slightly different database structure. It is almost never a good idea to serialize / json_encode data in your database. Since you already have a dedicated table for votes it should be simple to change your table from what you curretly have to the following:
id | user_id | feature | value
------------------------------
1 | 2 | sys | 50
2 | 2 | beta | 40
3 | 3 | sys | 50
This would make counting very trivial:
SELECT SUM(value) FROM table WHERE feature = 'sys'
Use array_sum
array_sum — Calculate the sum of values in an array
$voters = DB::table('votes')->get(); // get the JSON response response
$jsonDecodedArray = json_decode($voters,true); // decode the JSON
$sum = array_sum($jsonDecodedArray); // Use php array_sum

Fast method for Looping through Array to match a common ID in a second array

I'm trying to systematically loop through 2 arrays, and match their values for some quick processing. Let me set up my specific situation:
Array 1
productID,
companyID,
name,
price
Array 2
companyID,
name,
rebate1,
rebate2
I want to loop through Array 1, and when the companyID matches an ID inside of Array 2, I will do some quick math based on the rebate1, rebate2 values for that companyID.
Right now I am looping through Array 1, and then on EACH item in Array 1 I loop through the entire Array 2 to see if the companyID exists. I know this can't be the fastest/cleanest solution...
EDIT
The key values for Array 1 look like:
$array1[0]['productID']
$array1[0]['companyID'] (etc...)
$array1[1]['productID']
$array1[1]['companyID'] (etc...)
The key values for Array 2 look like:
$array2[0]['companyID']
$array2[0]['rebate1'] (etc...)
$array2[1]['companyID']
$array2[1]['rebate1'] (etc...)
Use the companyId as key for Array 2, i.e., make sure that
$Array2[$Array1[$i]['companyID']]['companyID'] == $Array1[$i]['companyID']
This gives you constant time lookup of companies in Array 2 based on companyID and you can do your calculation with
$Array2[$Array1[$i]['companyID']]['rebate1']`
and
$Array2[$Array1[$i]['companyID']]['rebate2']`
Example:
foreach ($Array1 as $value) {
if (isset($Array2[$value['companyID']])) {
//TODO: use $Array2[$value['companyID']] for calculation
} else {
// TODO: handle case companyID not in $Array2
}
}
What approximate sizes do you expect for each of your arrays?
While as you say, your method isn't certainly the fastest (looks like 0(n²)), below 10'000 elements in each array I doubt you can see any significant speed difference.
If you have 150'000 in array1 and 200'000 in array2, that's a whole other story and you'll have to look for an algorithm that is rather 0(log n).
Edit:
As mentioned above, let's just make your array associative if you can:
Instead of:
Array2 = array(
0 => array(
'Company_id' => 'Hello',
'rebate_1' => '50%',
)
);
Make it:
Array2 = array(
'Hello' => array(
'rebate_1' => '50%',
)
);
And then use:
if (isset(array2[$company_id]))
{
// do your stuff
}
If you can't modify Array2's structure where it's coming from, you should transform it on the fly in your search function's scope, so that it looks like above, and then use the transformed array. Transforming Array2 into an associative one shouldn't take too long, for the number of elements you say you have.
The easiest way I can think of is to use the companyID as the key for Array 2:
$companies[$companyID]=array($name,$rebate1,$rebate2)
and then you just reference it directly looping Array 1
$products[$x]=array($productID,$companyID,$name,$price);
...
$newprice1=$products[$x][3]/$companies[$products[$x][1]][1];
$newprice2=$products[$x][3]/$companies[$products[$x][1]][2];
My answer is slightly different from the first one, mind the arrays...
You can create a new array indexed by the company id as follows:
$cid = array_map(function($a) {return $a['companyID'];}, $array2);
$new2 = array_combine($cid, $array2);
With that, you can loop through the first array and access the data:
foreach ($array1 as $key => $value){
$rebate1 = $new2[$value['companyID']]['rebate1'];
$rebate2 = $new2[$value['companyID']]['rebate2'];
}

Categories