PHP - How to convert multiple JSON-like strings to associative array? - php

Input string:
$times = '{endTime:"2017-03-29T17:15:00.000+11:00",startTime:"2017-03-29T17:00:00.000+11:00"},{endTime:"2017-03-31T17:15:00.000+11:00",startTime:"2017-03-31T17:00:00.000+11:00"},{endTime:"2017-04-01T12:15:00.000+11:00",startTime:"2017-04-01T12:00:00.000+11:00"}';
And I'm trying to convert it into an array that should look like this:
Array
(
[0] => Array
(
endTime => "2017-03-29T17:15:00.000+11:00"
startTime => "2017-03-29T17:00:00.000+11:00"
)
[1] => Array
(
endTime => "2017-03-31T17:15:00.000+11:00"
startTime => "2017-03-31T17:00:00.000+11:00"
)
[2] => Array
(
endTime => "2017-04-01T12:15:00.000+11:00"
startTime => "2017-04-01T12:00:00.000+11:00"
)
)
I've tried exploding, combining and all sorts but my code is so messy that I'm sure there must be a better and cleaner way?
This is MY cleanest starting point, but even this not clean, yes?
$times = '{endTime:"2017-03-29T17:15:00.000+11:00",startTime:"2017-03-29T17:00:00.000+11:00"},{endTime:"2017-03-31T17:15:00.000+11:00",startTime:"2017-03-31T17:00:00.000+11:00"},{endTime:"2017-04-01T12:15:00.000+11:00",startTime:"2017-04-01T12:00:00.000+11:00"}';
$timesarr = explode("},{", $times);
foreach ($timesarr as $i => $item) {
$timesarr[$i] = str_replace("{", "", $item);
$timesarr[$i] = str_replace("}", "", $timesarr[$i]);
$timesarr[$i] = explode(",", $timesarr[$i]);
}
echo '<pre>'; print_r($timesarr); echo '</pre>';

Improvements done:
Appended square braces at starting and end.
Replaced words with [a-zA-Z]+ with "[a-zA-Z]+" making it a valid json than json_decode
PHP code demo
<?php
$times = '{endTime:"2017-03-29T17:15:00.000+11:00",startTime:"2017-03-29T17:00:00.000+11:00"},{endTime:"2017-03-31T17:15:00.000+11:00",startTime:"2017-03-31T17:00:00.000+11:00"},{endTime:"2017-04-01T12:15:00.000+11:00",startTime:"2017-04-01T12:00:00.000+11:00"}';
$times=$times."]";
$times="[".$times;
$jsonString=preg_replace("/([a-zA-Z]+\s*)\:/", '"$1":', $times);
print_r(json_decode($jsonString,true));

This code will replace 'endTime' with '"endTime"' and same for startTime. I don't recommend you doing it this way, but it will work for you in this situation:
$times='{"endTime":"2017-03-29T17:15:00.000+11:00","startTime":"2017-03-29T17:00:00.000+11:00"},{"endTime":"2017-03-31T17:15:00.000+11:00","startTime":"2017-03-31T17:00:00.000+11:00"},{"endTime":"2017-04-01T12:15:00.000+11:00","startTime":"2017-04-01T12:00:00.000+11:00"}';
$times=str_replace("endTime",'"endTime"',$times);
$times=str_replace("startTime",'"startTime"',$times);
$times="[$times]";
echo "<h2><pre>";
print_r(json_decode($times,true));
This will output this:
Array
(
[0] => Array
(
[endTime] => 2017-03-29T17:15:00.000+11:00
[startTime] => 2017-03-29T17:00:00.000+11:00
)
[1] => Array
(
[endTime] => 2017-03-31T17:15:00.000+11:00
[startTime] => 2017-03-31T17:00:00.000+11:00
)
[2] => Array
(
[endTime] => 2017-04-01T12:15:00.000+11:00
[startTime] => 2017-04-01T12:00:00.000+11:00
)
)

Try this
First make the string a valid json string.
Add [ at start and ] at end. So your code will be
$times = '[{endTime:"2017-03-29T17:15:00.000+11:00",startTime:"2017-03-29T17:00:00.000+11:00"},{endTime:"2017-03-31T17:15:00.000+11:00",startTime:"2017-03-31T17:00:00.000+11:00"},{endTime:"2017-04-01T12:15:00.000+11:00",startTime:"2017-04-01T12:00:00.000+11:00"}]';
$result = json_decode($times, true);

This is not valid JSON, it looks like a bunch of JS variables concatenated together. You need a heavily customised parser:
<?php
$times = '{endTime:"2017-03-29T17:15:00.000+11:00",startTime:"2017-03-29T17:00:00.000+11:00"},{endTime:"2017-03-31T17:15:00.000+11:00",startTime:"2017-03-31T17:00:00.000+11:00"},{endTime:"2017-04-01T12:15:00.000+11:00",startTime:"2017-04-01T12:00:00.000+11:00"}';
$times = str_replace(["{","}"],["\0","\0"],$times); //replace {} with null bytes (they're hopefully unique and will be used as delimiters)
$csv = str_getcsv($times,",","\0"); //Treat string as a CSV enclosed in those null bytes
$csv = array_map(function ($v) {
$vars = explode(",",$v);
$arr = [];
foreach ($vars as $var) {
$parts = str_getcsv($var,":","\""); // endTime:"2017-03-29T17:15:00.000+11:00" is like a CSV split by : and enclosed in "
$arr[$parts[0]] = $parts[1];
}
return $arr;
},$csv);
print_r($csv);
Result:
Array
(
[0] => Array
(
[endTime] => 2017-03-29T17:15:00.000+11:00
[startTime] => 2017-03-29T17:00:00.000+11:00
)
[1] => Array
(
[endTime] => 2017-03-31T17:15:00.000+11:00
[startTime] => 2017-03-31T17:00:00.000+11:00
)
[2] => Array
(
[endTime] => 2017-04-01T12:15:00.000+11:00
[startTime] => 2017-04-01T12:00:00.000+11:00
)
)
Alternately walk away from this mess and demand your data be properly formatted as JSON.

Related

Use array_column in combination with preg_match

Lets suppose we have an array of arrays that needs to be converted to rows
From this:
Array
(
[subject] => Array
(
[0] => EDN:LOC:DERR
[1] => EDN:LOC:DOXX
[2] => EDN:LOC:NTTT
[3] => EDN:LOC:NAGA
)
[object] => Array
(
[0] => ABS:D01::ADFPAZ01
[1] => ABS:D01::DOXYWITX
[2] => ABS:D01::NAGBAAD2
[3] => ABS:D01::NAGGAAD2
)
[units] => Array
(
[0] => ABS:D06::UNAA
[1] => ABS:D06::UMMM
[2] => ABS:D06::UPOP
[3] => ABS:D06::UPOP
)
To this:
[0] => "'DERR' , 'ADFPAZ01' , 'UNAA'"
[1] => "'DOXX' , 'DOXYWITX' , 'UMMM'"
[2] => "'NTTT' , 'NAGBAAD2' , 'UPOP'"
[3] => "'NAGA' , 'NAGGAAD2' , 'UPOP'"
So I need the arrays to be cleaned by a pattern and compressed into lines.
I managed the compact view with the following function
$array_res = array();
for ($i=0; $i<=$totalEntries-1; $i++) {
array_push($array_res, implode("', '", array_column($array_of_arrays, $i)));
}
My regex pattern is $pattern = '([^.:]*$)'; And it collects a sequence of letters from the end of the string until it finds a colon. And I used preg_match($pattern, $string, $match) to receive the proper string into the $match variable.
However, I cannot combine the above two procedures either with array_filter or array_map inside the for loop.
EDIT: Note that there can be a subarray that contains values without a colon. In that case we have to get the value as is
[units] => Array
(
[0] => NULL
[1] => VALUE1
[2] => VALUE2
[3] => NULL
)
Rather than using a regex, this just uses array_walk() to process the extracted column and for each item it uses strrchr() with : as the last character to match (although it will include the :, so uses substr() to remove the first char)...
for ($i=0; $i<=$totalEntries-1; $i++) {
$newRow = array_column($array_of_arrays, $i);
array_walk($newRow, function (&$data) {
$data = substr(strrchr(":".$data, ":") , 1);
});
$array_res[] = "'".implode("', '", $newRow)."'";
}
The part ":".$data deals with the time when there is no : in the string, it will always ensure that it does find something to use.
Other way:
$arr = [
'subject' => [ 'EDN:LOC:DERR', 'EDN:LOC:DOXX', 'EDN:LOC:NTTT', 'EDN:LOC:NAGA' ],
'object' => [ 'ABS:D01::ADFPAZ01', 'ABS:D01::DOXYWITX', 'ABS:D01::NAGBAAD2', 'ABS:D01::NAGGAAD2' ],
'units' => [ 'ABS:D06::UNAA', 'ABS:D06::UMMM', 'ABS:D06::UPOP', 'ABS:D06::UPOP' ]
];
$res = [];
$fmt = "'%s', '%s', '%s'";
foreach ($arr['subject'] as $k => $v) {
$res[] = vsprintf($fmt, preg_replace('~^.*:~', '', array_column($arr, $k)));
}
print_r($res);
Notice: If you don't know in advance your array length, nothing forbids to build the format pattern dynamically (using str_repeat or implode).

PHP Explode string between two characters to arrays? (Noob question)

Hello :) I am a beginner in PHP.
I tried several times but did not succeed
I would like to parse a String like :
[1,[01,11,12],[20,21,22]]
to
`
arr[0][0]=>1
arr[1][0]=>01
arr[1][1]=>11
arr[1][2]=>12
arr[2][0]=>20
arr[2][1]=>21
arr[2][2]=>22
`
You can split your string on a comma that is not enclosed by [ and ] using this regex (inspired by this answer) with preg_split:
,(?![^\[]*\])
and then trim surrounding [ and ] from the resultant parts and split those strings on commas into succeeding elements of the output array. For example:
$string = '[1,[01,11,12] ,4 ,5, [20,21,22]]';
$parts = preg_split('/,(?![^\[]*\])/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
$output = array();
foreach ($parts as $part) {
$part = trim($part, '[] ');
$output[] = explode(',', $part);
}
print_r($output);
Output:
Array
(
[0] => Array
(
[0] => 1
)
[1] => Array
(
[0] => 01
[1] => 11
[2] => 12
)
[2] => Array
(
[0] => 4
)
[3] => Array
(
[0] => 5
)
[4] => Array
(
[0] => 20
[1] => 21
[2] => 22
)
)
Demo on 3v4l.org
If you're 100% certain of the source and safety of the string, you can also just use eval:
eval("\$output = $string;");
The result will be the same.

Convert string to array php

I have a string like this:
{ArrivalTime:300, ProductID:198, ArrivalDate:21/07/2017}, {ArrivalTime:582, ProductID:397, ArrivalDate:22/07/2017}
I used json_decode() but it's not working;
I need return array like this:
Array
(
[0] => Array
(
[ArrivalTime] => 300
[ProductID] => 198
[ArrivalDate] => 21/07/2017
)
[1] => Array
(
[ArrivalTime] => 582
[ProductID] => 397
[ArrivalDate] => 21/07/2017
)
)
Can you help me to do that? thanks.
You can try
str_split — Convert a string to an array
Syntax:
array str_split ( string $string [, int $split_length = 1 ] )
Example:
<?php
$str = "Hello Friend";
$arr1 = str_split($str);
print_r($arr1);
?>
Edit:
Output:
Array
(
[0] => H
[1] => e
[2] => l
[3] => l
[4] => o
[5] =>
[6] => F
[7] => r
[8] => i
[9] => e
[10] => n
[11] => d
)
Replace string name and array name your own.
Thank You.
Run follow code to analyse it:
function strAnalyse($str){
preg_match_all('/(?<={)[^{}]*(?=})/',$str,$match);
$result = array();
foreach($match[0] as $item){
$one =array();
$tmp = explode(',',$item);
foreach($tmp as $kv){
$a = explode(':',$kv);
$one[trim($a[0])] = trim($a[1]);
}
array_push($result,$one);
}
echo '<pre>';
print_r($result);
}
result:
Array
(
[0] => Array
(
[ArrivalTime] => 300
[ProductID] => 198
[ArrivalDate] => 21/07/2017
)
[1] => Array
(
[ArrivalTime] => 582
[ProductID] => 397
[ArrivalDate] => 22/07/2017
)
)
the json is invalid even if we add "[]" (array brackets)
value should be in the any one of the format :
string, number,object,array,true,false,null
in your case there is a date in the value field change it to string by enclosing ""(double quotes)
the key in your json is a string
for json key the string should be enclosed by ""(double quotes)
" chars "
offical documentation : http://www.json.org/
the correct json format for your json is
[{
"ArrivalTime": 300,
"ProductID": 198,
"ArrivalDate": "21 / 07 / 2017"
}, {
"ArrivalTime": 582,
"ProductID": 397,
"ArrivalDate": "22 / 07 / 2017"
}]
You need to wrap your "json" string with [] and quotes, of course (or check, why it not wrapped earlier):
[{"ArrivalTime": 300,"ProductID": 198,"ArrivalDate": "21 / 07 / 2017"}, {"ArrivalTime": 582,"ProductID": 397,"ArrivalDate": "22 / 07 / 2017"}]
Then it will be correct json format and json_decode() create correct array.
That is not a valid json format. But if you have such kinda string try this code:
$string = "{ArrivalTime:300, ProductID:198, ArrivalDate:21/07/2017}, {ArrivalTime:582, ProductID:397, ArrivalDate:22/07/2017}";
$key = $value = $resultArray= array();
$arrayJson = explode('}, ', $string);
foreach ($arrayJson as $arrayJsonRep) {
$repJson = str_replace('{', '', $arrayJsonRep);
$repJson = str_replace('}', '', $repJson);
$repJsonExp = explode(', ', $repJson);
foreach ($repJsonExp as $x) {
$repJsonExpfirst= explode(':', $x);
array_push($key, $repJsonExpfirst[0]);
array_push($value, $repJsonExpfirst[1]);
}
$finalArray = array_combine($key, $value);
array_push($resultArray, $finalArray);
}
print_r($resultArray);

Categorizing MySQL result array

I have a function that returns database results like so:
<?php print_r($homepagematches; ?>
Array
(
[0] => Array
(
[matchid] => 30
[matchtitle] => Testing This!
[matchaverage] => 1
[matchyoutubecode] => New Match
[casterid] => 1
[matchtype] =>
[matchdate] => 2013-05-24 02:19:49
[matchcasteryoutube] => http://youtube.com/huskystarcraft
[matchcaster] => HuskyStarcraft
)
[1] => Array
(
[matchid] => 27
[matchtitle] => Psy vs Camara
[matchaverage] => 1
[matchyoutubecode] => nefC9vkMfG8
[casterid] => 1
[matchtype] =>
[matchdate] => 2013-05-24 02:13:10
[matchcasteryoutube] => http://youtube.com/huskystarcraft
[matchcaster] => HuskyStarcraft
)
The function returns all matches within the last 3 days, What I am trying to figure out is how to reform the array so that I can display the matches under the day in which they were posted. I know a foreach loop is probably required for this, I just can't get my head around the concept I would need to implement.
$matchdate = '';
foreach($this->data['homepagematches'] as $match){
if($matchdate != date('m/d', strtotime($match['matchdate'])) || $matchdate == ''){
$homematch[date('m/d', strtotime($match['matchdate']))] = array(
"matchtitle" => $match['matchtitle']);
}
Basically I need the Array to look like:
Array
(
[05/24] => Array
(
[matchid] =>30
[matchtitle] => Testing This!
[matchyoutubecode] => New Match
[casterid] = 1
)
)
I think this should do it.
foreach($this->data['homepagematches'] as $match){
$tag = date('m/d', strtotime($match['matchdate']));
$data[$tag][] = array(
"matchid" => $match['matchid'],
"matchtitle" => $match['matchtitle'],
"matchyoutubecode" => $match['matchyoutubecode'],
"casterid" => $match['casterid']
);
}
print_r($data);
<?php
$MatchesByDate = array();
foreach($homepagematches as $match) {
list($matchdate,$time) = explode(" ",$match["matchdate"]); //split field into date and time
if( !isset($MatchesByDate[$matchdate]) )
$MatchesByDate[$matchdate] = array(); // If the array for that date doesnt exist yet make it
$MatchesByDate[$matchdate][] = $match; //Use the matchdate as a key and add to the array
}

how to sort particular strings from an array of values in php?

$array = array("2011-September_38","2011-June_4","2010-November_9","2011-November_29","2010-December_19");
i want to sort this array strings as following, it should sort the year first, then it should sort the month,
DESIRED OUTPUT
Array ( [0] => 2010-Marh_19
[1] => 2010-November_9
[2] => 2011-June_4
[3] => 2011-September_38
[4] => 2011-November_29 )
I've tried something, could anyone bind my function to sort year then month http://codepad.org/skEiUkTC
Try this code:
<?php
$array = array("2011-September_38","2011-June_4","2010-November_9","2011-November_29","2010-December_19");
function monthCompare($a, $b) {
$da = strtotime(strstr($a, '_', true));
$db = strtotime(strstr($b, '_', true));
return $da > $db;
}
usort($array, "monthCompare");
print_r($array);
?>
OUTPUT
Array
(
[0] => 2010-November_9
[1] => 2010-December_19
[2] => 2011-June_4
[3] => 2011-September_38
[4] => 2011-November_29
)
So a simple solution to this, is to turn each of the values into a objects with DateTime::createFromFormat, sort them, and then outputting the values again.
Before i saw this question i had never played with DateTime objects, but they are awesome and easy to work with, and createFromFormat makes perfectly sense.
$array = array("2011-September_30","2011-June_4","2010-November_9","2011-November_29","2010-December_19");
foreach($array as $item)
{
$timestamps[] = DateTime::createFromFormat('Y-F_d',$item);
}
sort($timestamps);
foreach($timestamps as $timestamp)
{
$newarray[] = $timestamp->format('Y-F_d');
}
will give you
Array
(
[0] => 2010-November_09
[1] => 2010-December_19
[2] => 2011-June_04
[3] => 2011-September_30
[4] => 2011-November_29
)

Categories