incremented json keys, parsing CSV - php

I'm using mailparser.io to parse a .csv attachment and make an http post to another cloud service. The problem is the json received is not an associative array but rather key values are incremented:
First_Name::1 = "John"
First_Name::2 = "Sally"
First_Name::3 = "Kenneth"
Last_Name::1 = "Smith"
Last_Name::2 = "Johnson"
Last_Name::3 = "Cline"
Using PHP, how can I reformat this into a usable json associative array and retain the index, something like:
{"Record":"1","First_Name":"John","Last_Name":"Smith"}
{"Record":"2","First_Name":"Sally","Last_Name":"Johnson"}
{"Record":"3","First_Name":"Kenneth","Last_Name":"Cline"}
The number of rows will vary, but the columns will always be the same. So I assume I can count the number of key:value pairs and divide by the number of columns. My example would provide 6 pairs, dividing by 2 columns would yield 3 sets. Create an incremental loop and retrieve/build a usable json string.
$count = count($string);
$rows = $count/2;
$index = 0;
while($index <= $rows) {
**get First_Name::1, Last_Name::1 and build json**
$index++;
}
Yes, I realize mailparser will create an http post for each row in a csv, but it won't keep them in the original row order and I need to preserve that.
I've been able to tweak some settings in mailparser and now am receiving it as
"Record":[{"0":"John","1":"Smith"},
{"0":"Sally","1":"Smith"},
{"0":"Kenneth","1":"Cline"}
]

Related

How to perform set difference between a data stream and a list (exclusion list) in PHP

I have a data stream in a loop. This retrieved results row by row from the database. However, I want to person a form of array-diff between the stream and a given array. The given array is an exclusion list say list of blacklisted users. So this is what I have so far.
This is a fictitious example. I don't want to write all the database codes retrieving results in row by row basis
database objects containing ("Volvo","BMW","Toyota"); //assume that this is a continous stream of data from a database where we don't know the total elements. Just that single element
$toys=array("BMW","Toyota"); //assume that this is a list of blacklisted users
for($rindex=0; $rindex < count($cars); $rindex++)
{
for($index=0; $index < size(database objects); $index++)
{
//obtain the database object on a row by row basis
if (strcmp ( $cars[$rindex] , $toys[$index] )!=0) //specify exclusion
{
echo $cars[$rindex];
}
}
}
The expected answer should be Volvo. This could be done easily if we know all the element in $cars so we can't use array-diff($cars,$toys). Assume that $cars is a continuous stream say a database result on a row by row basis. How could we do array-diff() between a fixed known blacklisted array and a continuous stream of data
Remember array-diff() cannot be used as we do not know the full size of the data stream or all the the element in the stream as we begin.
This can be done using array-filter() but I already have performance issues and want to do this operation online.
Kindly provide answers in PHP.
Lookup arrays quickly - the code is commented and tested. PHP 5.3.18
<?php // Q22754093
// database objects containing ("Volvo","BMW","Toyota"); //assume that this is a continous stream of data from a database where we don't know the total elements. Just that single element
$allToys = array("Volvo","BMW","Toyota");
// use the 'toy' as the array key -- there is no faster way of checking whether
// something is in an array, especially if the array is large.
$badToys = array("BMW" => true,
"Toyota" => true); //assume that this is a list of blacklisted users
// by setting them false then you treat them as
// 'good' if you wish - whatever
$checkedGoodToys = array();
$checkedBadToys = array();
//obtain the database object on a row by row basis
foreach($allToys as $oneToy)
{
if (isBadToy($oneToy)) {
// do what you want with the bad toy...
$checkedBadToys[] = $oneToy;
}
else {
// do what you want with the good toy...
$checkedGoodToys[] = $oneToy;
}
}
var_dump($checkedGoodToys, 'The Good Toys');
var_dump($checkedBadToys, 'The Bad Toys');
exit;
// check if the toy is in the badToy array
function isBadToy($theToy)
{
global $badToys;
return isset($badToys[$theToy]) && $badToys[$theToy];
}
in_array() did the trick. Thanks for all your answers.
database objects containing ("Volvo","BMW","Toyota"); //assume that this is a continous stream of data from a database where we don't know the total elements. Just that single element
$toys=array("BMW","Toyota"); //assume that this is a list of blacklisted users
for($rindex=0; $rindex < count($cars); $rindex++)
{
for($index=0; $index < size(database objects); $index++)
{
//obtain the database object on a row by row basis
if (in_array($cars[$rindex] , $toys) //specify exclusion
{
echo $cars[$rindex];
}
}
}

PHP spontaneously creates associative array where indexed array is required - using PHP arrays with Highcharts

I'm using PHP to retrieve data from an SQL database to produce a stacked column chart in Highcharts. The idea is that I'm taking the following piece of code to retrieve values from my database. This code should generate an array which then gets encoded to JSON and passed to Highcharts; this code produces a single 'part' of a stacked column, and the index determines which vertical bar that part is in. (So in http://www.highcharts.com/demo/column-stacked, the index would represent which fruit, and the data in this series would represent one person/color.)
The issue is that when I run this code, instead of ending up with an indexed array of data grouped by category, such as
[12,13,14,15] where each item is a category, I end up with an associative array where the indexes I specified in the code are turned into a string key.
{"1":13,"0":12,"3":14, "2":13, "5":15}
Because my indexes are being interpreted as associative keys and not as the indexed locations of the data inside the array, the data is now being added to locations in the order that I retrieved the data, and not assigned to a location in the array based on the index I give. Highcharts assigns categories based on location in the array, and not on key, so all my data ends up in the wrong categories.
Is there a way to get PHP to treat my carefully collected indexes as indexes and not as keys, and add my data points in the location in the array indicated by the indexes? I'm kind of new to PHP, and Java and C++ - the languages I've worked with before - don't have associative arrays, so any help you can give me in explaining and fixing this undesired behavior would be much appreciated.
Code below.
$variable indicates what the data is being sorted into categories by, and $r is the variable representing the array of the SQL query, so $r['variable'] is the category of this data point, and $r['amount'] is the data point itself.
$found = -1;
//if this is the first set of data being collected
if (count($category['data']) == 0){
$category['data'][0] = $r[$variable];
$series1['data'][0] = floatval($r['amount']);
$count++;
$times1[0]++;
}
//if it's not the first set of data, find out if this category has been used before
else {
for ($x = 0; $x < count($category['data']); $x++){
if ($r[$variable] == $category['data'][$x]){
$found = $x;
break;
}
}
// if that category does not already exist, add it, and add the data
if ($found == -1) {
$times1[$count]++;
$category['data'][$count] = $r[$variable];
$series1['data'][$count] = floatval($r['amount']);
$count++;
}
else { //otherwise, add its data to the data already in the current category. This will eventually yield an average, with $times1[] as the divisor
$times1[$found]++;
$series3['data'][$found] = floatval((floatval($series3['data'][$found]) + floatval($r['amount'])));
}}
Go through with below code hope it will give some idea to resolve your problem --
<?php
$jsonstring = '{"1":13,"0":12,"3":14, "2":13, "5":15}';
$tempArr = json_decode($jsonstring, true);
asort(tempArr); // for sorting the array --
//run another foreach to get created an array --
$finArr = array();
foreach(tempArr as $key=>$val){
$finArr[] = $val;
}
$requiredjsonString = json_encode(finArr); // it will return your required json Array [12,13,14,15]
?>
Edit: I advice also set JSON_NUMERIC_CHECK flag in json_encode();

create a multidimensional array in a loop php

I've done a fair bit of googling and couldn't find anything that works, I'm just getting nothing back, this is probably something simple but there's a lot of variations that don't seem to match what I'm doing.
To give you an overall idea what I'm at, I'm accessing an API and getting back info as an object. There are comments and attachments, these are in separate arrays.
What i want to do is display the comments and attachments all together in the order of the date and time not separately.
I figured the best way is to create a loop through the comments array, then create a loop through the attachment array, then join both and sort by the date (epoch) and then loop through the whole merged loop echoing what i want. That should provide some context, right now i just want to create the multidimensional array for comments and i can figure out the rest.
$comments_holder = array();
//total number of comments in the array
$comment_total = $issue_json->fields->comment->total -1;
$i=1;
while ($i <= $comment_total)
{
//this is the date,time and timezone info for each comment
$raw_date = $issue_json->fields->comment->comments[$i]->updated;
$comments_holder[$i] = array();
//convert_sql_time just converts from 2012-11-04T16:33:00.936+600 into epoch time so i can sort the results later based on date
$comments_holder[$i]['comments_date'] = convert_sql_time($raw_date);
$comments_holder[$i]['comments_displayName'] = $issue_json->fields->comment->comments[$i]->author->displayName;
$comments_holder[$i]['comments_body'] = $issue_json->fields->comment->comments[$i]->body;
}
if everything is okay with data, this code will be enough for building such array:
$comments = $issue_json->fields->comment->comments;
$result = array();
foreach ($comments as $comment) {
$result[] = array(
'comments_date' => convert_sql_time($comment->updated),
'comments_displayName' => $comment->author->displayName,
'comments_body' => $comment->body,
);
}
print_r($result);
if comment->comments is an array, there is no need to keep it's count separately;
foreach is enough for iterating through the array and there is no need to keep separate variable for calculating array index;
[] notation will automatically increase array index and assigning array directly will do the trick(i.e. will result to multi dim array)

Autofill array with empty data to match another array size

I have 2 sets of arrays:
$dates1 = array('9/12','9/13','9/14','9/15','9/16','9/17');
$data1 = array('5','3','7','7','22','18');
// for this dataset, the value on 9/12 is 5
$dates2 = array('9/14','9/15');
$data2 = array('12','1');
As you can see the 2nd dataset has fewer dates, so I need to "autofill" the reset of the array to match the largest dataset.
$dates2 = array('9/12','9/13','9/14','9/15','9/16','9/17');
$data2 = array('','','12','1','','');
There will be more than 2 datasets, so I would have to find the largest dataset, and run a function for each smaller dataset to properly format it.
The function I'd create is the problem for me. Not even sure where to start at this point. Also, I can format the date and data arrays differently (multidimensional arrays?) if for some reason that is better.
You can do this in a pretty straightforward manner using some array functions. Try something like this:
//make an empty array matching your maximum-sized data set
$empty = array_fill_keys($dates1,'');
//for each array you wish to pad, do this:
//make key/value array
$new = array_combine($dates2,$data2);
//merge, overwriting empty keys with data values
$new = array_merge($empty,$new);
//if you want just the data values again
$data2 = array_values($new);
print_r($data2);
It would be pretty easy to turn that into a function or put it into a for loop to operate on your array sets. Turning them into associative arrays of key/value pairs would make them easier to work with too I would think.
If datas are related will be painful to scatter them on several array.
The best solution would be model an object with obvious property names
and use it with related accessor.
From your question I haven't a lot of hint of what data are and then I have to guess a bit:
I pretend you need to keep a daily log on access on a website with downloads. Instead of using dates/data1/data2 array I would model a data structure similar to this:
$log = array(
array('date'=>'2011-09-12','accessCount'=>7,'downloadCount'=>3),
array('date'=>'2011-09-13','accessCount'=>9), /* better downloadsCount=>0 though */
array('date'=>'2011-09-15','accessCount'=>7,'downloadCount'=>3)
...
)
Using this data structure I would model a dayCollection class with methods add,remove,get,set, search with all methods returning a day instance (yes, the remove too) and according signature. The day Class would have the standard getter/setter for every property (you can resolve to magic methods).
Depending on the amount of data you have to manipulate you can opt to maintain into the collection just the object data (serialize on store/unserialize on retrieve) or the whole object.
It is difficult to show you some code as the question is lacking of details on your data model.
If you still want to pad your array than this code would be a good start:
$temp = array($dates, $data1, $data2);
$max = max(array_map('count',$temp));
$result = array_map( function($x) use($max) {
return array_pad($x,$max,0);
}, $temp);
in $result you have your padded arrays. if you want to substitute your arrays do a simple
list($dates, $data1, $data2) = array_map(....
You should use hashmaps instead of arrays to associate each date to a data.
Then, find the largest one, cycle through its keys with a foreach, and test the existence of the same key in the small one.
If it doesn't exist, create it with an empty value.
EDIT with code (for completeness, other answers seem definitely better):
$dates_data1 = array('9/12'=>'5', '9/13'=>'3', '9/14'=>'7' /* continued */);
$dates_data2 = array('9/14'=>'12', '9/15'=>'1');
#cycle through each key (date) of the longest array
foreach($dates_data1 as $key => $value){
#check if the key exists in the smallest and add '' value if it does not
if(!isset( $date_data2[$key] )){ $date_data2[$key]=''; }
}

php, get values from matrix (array)

I have Matrix and how get value from there?
The data obtained from a file, so that the matrix can be of different sizes
Thanks
Hypothetically (because the question is vague), if you read the contents in and have the results stored in a two-dimensional array, then you would use brackets to find the cell value. For example, here's reading in the contents into a multidimensional array called $matrix:
$contents = file_get_contents("myfile.csv");
$splitlines = explode("\n",$contents);//split the contents into rows
$matrix = array();
foreach($splitlines as $line){
$row = explode(",",$line);//split each line into columns
$matrix[] = $row;//add the array of columns as a new row in the matrix
}
now address any of the values in the matrix:
$samplevalue = $matrix[2][1]; //addresses the third row, second column.

Categories