Reputation: 9
I am having this string:
0&39avfy;&39avfy;task&39avfy;rose&39avfy;duration&39avfy;1.25&39avfy;user&39avfy;15&39avfy;1&39avfy;&39avfy;task&39avfy;daisy&39avfy;duration&39avfy;0.75&39avfy;user&39avfy;25&39avfy;2&39avfy;&39avfy;task&39avfy;orchid&39avfy;duration&39avfy;1.15&39avfy;user&39avfy;7
I need a 2d array like this:
array(
array(
"task" => "rose",
"duration" => 1.25,
"user" => 15
),
array(
"task" => "daisy",
"duration" => 0.75,
"user" => 25,
),
array(
"task" => "orchid",
"duration" => 1.15,
"user" => 7
)
);
Upvotes: 0
Views: 599
Reputation: 47894
Here is a way to split the string into an array of lines/rows, then parse each row with sscanf()
.
Code: (Demo)
$input = "0&39avfy;&39avfy;task&39avfy;rose&39avfy;duration&39avfy;1.25&39avfy;user&39avfy;15&39avfy;1&39avfy;&39avfy;task&39avfy;daisy&39avfy;duration&39avfy;0.75&39avfy;user&39avfy;25&39avfy;2&39avfy;&39avfy;task&39avfy;orchid&39avfy;duration&39avfy;1.15&39avfy;user&39avfy;7";
$delim = '&39avfy;';
$result = [];
foreach (preg_split('/' . $delim . '(?=\d+' . $delim . $delim . ')/', $input) as $row) {
[
$i,
$k,
$result[$i][$k],
$k,
$result[$i][$k],
$k,
$result[$i][$k]
] = sscanf($row, "%[^&]$delim" . str_repeat("$delim%[^&]", 6));
}
var_export($result);
Or if you don't know how many key-value pairs to expect, use the \G
(continue metacharacter) to continue matching key-value pairs after encountering the row id number. Demo
$regex = <<<REGEX
/
(\d+)&39avfy;
|\G(?!^)&39avfy;([^&]+)&39avfy;([^&]+)
/x
REGEX;
preg_match_all($regex, $input, $m, PREG_SET_ORDER);
$result = [];
foreach ($m as $set) {
if (strlen($set[1])) {
$index = $set[1];
} else {
$result[$index][$set[2]] = $set[3];
}
}
var_export($result);
Output (from either snippet):
array (
0 =>
array (
'task' => 'rose',
'duration' => '1.25',
'user' => '15',
),
1 =>
array (
'task' => 'daisy',
'duration' => '0.75',
'user' => '25',
),
2 =>
array (
'task' => 'orchid',
'duration' => '1.15',
'user' => '7',
),
)
Upvotes: 0
Reputation: 3056
At least this solves your problem.
<?php
$in = '0&39avfy;&39avfy;task&39avfy;rose&39avfy;duration&39avfy;1.25&39avfy;user&39avfy;15&39avfy;1&39avfy;&39avfy;task&39avfy;daisy&39avfy;duration&39avfy;0.75&39avfy;user&39avfy;25&39avfy;2&39avfy;&39avfy;task&39avfy;orchid&39avfy;duration&39avfy;1.15&39avfy;user&39avfy;7';
$arr = explode('&39avfy;',$in);
$out = array();
$i = 0;
foreach($arr as $a){
switch ($i) {
case 0:
if(isset($tmp)) { $out[] = $tmp; }
break;
case 3:
$tmp["task"] = $a;
break;
case 5:
$tmp["duration"] = $a;
break;
case 7:
$tmp["user"] = $a;
break;
default:
}
$i++;
$i%=8;
}
if($i == 0 && isset($tmp)) { $out[] = $tmp; }
var_dump($out);
array(3) {
[0]=>
array(3) {
["task"]=>
string(4) "rose"
["duration"]=>
string(4) "1.25"
["user"]=>
string(2) "15"
}
[1]=>
array(3) {
["task"]=>
string(5) "daisy"
["duration"]=>
string(4) "0.75"
["user"]=>
string(2) "25"
}
[2]=>
array(3) {
["task"]=>
string(6) "orchid"
["duration"]=>
string(4) "1.15"
["user"]=>
string(1) "7"
}
}
this code leads to the same result:
<?php
$in = '0&39avfy;&39avfy;task&39avfy;rose&39avfy;duration&39avfy;1.25&39avfy;user&39avfy;15&39avfy;1&39avfy;&39avfy;task&39avfy;daisy&39avfy;duration&39avfy;0.75&39avfy;user&39avfy;25&39avfy;2&39avfy;&39avfy;task&39avfy;orchid&39avfy;duration&39avfy;1.15&39avfy;user&39avfy;7';
$matches = array();
$regex = '/(\\d)&39avfy;&39avfy;task&39avfy;(.+?)&39avfy;duration&39avfy;(\\d+\\.\\d+)&39avfy;user&39avfy;(\\d+)/';
preg_match_all($regex, $in, $matches, PREG_SET_ORDER );
$out = array();
foreach($matches as $m){
$tmp = array();
$tmp['task'] = $m[2];
$tmp['duration'] = $m[3];
$tmp['user'] = $m[4];
$out[$m[1]] = $tmp;
}
var_dump($out);
Upvotes: 1
Reputation: 145482
Well, since it is uniformly ordered you can use this approach:
preg_match_all('#
task &39avfy; (?<task> [^&]*) .*?
duration &39avfy; (?<duration> [^&]*) .*?
user &39avfy; (?<user> [^&]*)
\K #x',
$str, $matches, PREG_SET_ORDER);
It will have some numeric array entries, but you can filter them out. More importantly, this is easier to adapt should your delimiter change.
print_r($matches);
[0] => Array
(
[0] =>
[task] => rose
[1] => rose
[duration] => 1.25
[2] => 1.25
[user] => 15
[3] => 15
)
[1] => Array
(
[0] =>
[task] => daisy
[1] => daisy
[duration] => 0.75
[2] => 0.75
[user] => 25
[3] => 25
)
Upvotes: 2