How to convert this string into an array - php

I have a string being returned from my database that I want to use as an array. It is already in an assoc array form. Here is a sample of what this looks like so far. How would I do this?
'test1' => 'value 1',
'test1' => 'value 1a,
'test2' => 'value 2'
Ok, this is the database code:
SELECT
inventory.invId,
GROUP_CONCAT(CONCAT( '''', inventory.vehicle, ''' => ', '''', inventory.color, '''' )) AS vehicle,
vehicle.vehicle_id
FROM
inventory
Inner Join vehicle ON vehicle.invId = inventory.invId
This is the print_r from the database results
Array
(
[0] => Array
(
[system] => AR3
[vehicle] => 'geo' => 'red', 'honda' => 'blue', 'ford' => 'black'
[vehicle_id] => 1232132
)
)

I'd strongly advise against returning data in such a format. First of all, you need to take much more care creating this special format to make it parse-able. What if a value contains the character "'"? You'd get 'key' => 'value '', which will throw the whole parsing process for a loop. Secondly, it's a non-trivial form to parse and would require a lexer or using the PHP tokenizer, which is much more work than it's worth.
For transporting native structures in strings, there's a special serialized format. You're just reinventing the wheel here. Badly, I might add. :)
Just return the results as normal SELECT * FROM table … and build the array in PHP, that's the proven and fastest way to do it.

$f = array();
$a1 = explode( ',', $string );
foreach( $a1 as $s ) {
$a2 = explode( '=>', $s ) {
$a2[0] = preg_replace( "/^'/", '', $a2[0] );
$a2[0] = preg_replace( "/'\s*$/", '', $a2[0] );
$a2[1] = preg_replace( "/^\s*'/", '', $a2[1] );
$a2[1] = preg_replace( "/'$/", '', $a2[1] );
$f[$a2[0]] = $a2[1];
}
}
note: Thanks for adding the code block formatting codaddict! ... Ps agree with answer on how to return result better: this is just a literal answer to Q

Related

How to parse a mostly consistent filename into meaningful parts?

I have filenames like:
1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf
Luckily, the file naming is pretty consistent, but I can't absolutely guarantee that someone didn't use a space where they should have used an underscore.
With this in mind, I want to parse the string and extract the following details:
$project_no = '1234
$series_no = '56
$sheet_no = '78'
$revision = 'D'
$title = 'A Fairly Short Title'
Presently, I use the following to grab this info:
$filename = $_FILES['file']['name'][$i];
$filename = preg_replace('/\\.[^.\\s]{3,4}$/', '', $filename);
$parts = preg_split( "(_| )", $filename );
$project_no = $parts[0];
$series_no = $parts[1];
$sheet_no = $parts[2];
$revision = end($parts);
$title is simply everything that's left over after removing $parts[0] $parts[1], $parts[2], and end($parts), but how should I express that?
I thought I might be able to use
$title = implode(' ',\array_diff_key($parts, [0,1,2,end($parts)]));
But this doesn't remove the $revision bit at the end...
$title = FLOOR AS PROPOSED D
What am I missing, and am I unnecessarily over-complicating this?
The array_diff_key looks at key comparison of both arrays. end() just moves the internal pointer of the array and is actually useless since the value returned from it can't be used in computing difference between 2 arrays' keys.
Current comparison behaves as
array_diff_key([0,1,2,3,4,5,6,7], [0,1,2,'D'])
which looks key wise as:
array_diff_key([0,1,2,3,4,5,6,7], [0,1,2,3])
Hence, the end result of implode is concatenation of 4,5,6,7 keys' values.
To make the second parameter array values as keys, you can use array_flip to make keys as values and values as keys with the below expression:
$title = implode(' ',\array_diff_key($parts, array_flip([0,1,2,count($parts)-1])));
Demo: https://3v4l.org/J6b5r
I fear you are over-complicating this. I think a single preg_match() call is the most direct way to parse your string.
It looks like you grabbed the regex pattern from https://stackoverflow.com/a/2395905/2943403 to trim the extension from your filename; however, I recommend using a regex function when a single non-regex function serves the same purpose.
pathinfo($filename', PATHINFO_FILENAME)
Now that the extension has been removed, let's move on to the parsing.
Code: (Demo)
$filename = '1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf';
preg_match('~([^ _]+)[ _]([^ _]+)[ _]([^ _]+)[ _](.+)[ _](\S)~', pathinfo($filename, PATHINFO_FILENAME), $m);
var_export([
'project_no' => $m[1],
'series_no' => $m[2],
'sheet_no' => $m[3],
'title' => str_replace('_', ' ', $m[4]),
'revision' => $m[5],
]);
Output:
array (
'project_no' => '1234',
'series_no' => '56',
'sheet_no' => '78',
'title' => 'A FAIRLY SHORT TITLE',
'revision' => 'D',
)
If you are deadset on using preg_split(), then the pattern becomes super simple, but there is a little more mopping up to do.
Code: (Demo)
$filename = '1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf';
$m = preg_split('~ |_~', pathinfo($filename, PATHINFO_FILENAME));
$revision = array_pop($m);
var_export([
'project_no' => $m[0],
'series_no' => $m[1],
'sheet_no' => $m[2],
'title' => implode(' ', array_slice($m, 3)),
'revision' => $revision,
]);
// same output as earlier snippet

Get matches from a preg_replace and use them as an array key

I want to get matches from a String and use them in a array as key to change the value in the string to the value of the array.
If it would be easier to realize, i can change the fantasy tags from %! also to whatever don't have problems in JS/jQuery. This script is for external JS Files and change some variables, which I can't Access from JS/jQuery. So I want to insert them with PHP and send them minified and compressed to the Browser.
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$string = preg_replace('%!(.*?)!%',$array[$1],$string);
echo $string;
You can use array_map with preg_quote to turn the keys of your array into regexes, and then use the values of the array as replacement strings in the array form of preg_replace:
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$regexes = array_map(function ($k) { return "/" . preg_quote("%!$k!%") . "/"; }, array_keys($array));
$string = preg_replace($regexes, $array, $string);
echo $string;
Output:
This is just a Test String and i wanna Change the Variable
Demo on 3v4l.org

PHP - preg_replace on an array not working as expected

I have a PHP array that looks like this..
Array
(
[0] => post: 746
[1] => post: 2
[2] => post: 84
)
I am trying to remove the post: from each item in the array and return one that looks like this...
Array
(
[0] => 746
[1] => 2
[2] => 84
)
I have attempted to use preg_replace like this...
$array = preg_replace('/^post: *([0-9]+)/', $array );
print_r($array);
But this is not working for me, how should I be doing this?
You've missed the second argument of preg_replace function, which is with what should replace the match, also your regex has small problem, here is the fixed version:
preg_replace('/^post:\s*([0-9]+)$/', '$1', $array );
Demo: https://3v4l.org/64fO6
You don't have a pattern for the replacement, or a empty string place holder.
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject)
Is what you are trying to do (there are other args, but they are optional).
$array = preg_replace('/post: /', '', $array );
Should do it.
<?php
$array=array("post: 746",
"post: 2",
"post: 84");
$array = preg_replace('/^post: /', '', $array );
print_r($array);
?>
Array
(
[0] => 746
[1] => 2
[2] => 84
)
You could do this without using a regex using array_map and substr to check the prefix and return the string without the prefix:
$items = [
"post: 674",
"post: 2",
"post: 84",
];
$result = array_map(function($x){
$prefix = "post: ";
if (substr($x, 0, strlen($prefix)) == $prefix) {
return substr($x, strlen($prefix));
}
return $x;
}, $items);
print_r($result);
Result:
Array
(
[0] => 674
[1] => 2
[2] => 84
)
There are many ways to do this that don't involve regular expressions, which are really not needed for breaking up a simple string like this.
For example:
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = array_map(function ($n) {
$o = explode(': ', $n);
return (int)$o[1];
}, $input);
var_dump($output);
And here's another one that is probably even faster:
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = array_map(function ($n) {
return (int)substr($n, strpos($n, ':')+1);
}, $input);
var_dump($output);
If you don't need integers in the output just remove the cast to int.
Or just use str_replace, which in many cases like this is a drop in replacement for preg_replace.
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = str_replace('post: ', '', $input);
var_dump($output);
You can use array_map() to iterate the array then strip out any non-digital characters via filter_var() with FILTER_SANITIZE_NUMBER_INT or trim() with a "character mask" containing the six undesired characters.
You can also let preg_replace() do the iterating for you. Using preg_replace() offers the most brief syntax, but regular expressions are often slower than non-preg_ techniques and it may be overkill for your seemingly simple task.
Codes: (Demo)
$array = ["post: 746", "post: 2", "post: 84"];
// remove all non-integer characters
var_export(array_map(function($v){return filter_var($v, FILTER_SANITIZE_NUMBER_INT);}, $array));
// only necessary if you have elements with non-"post: " AND non-integer substrings
var_export(preg_replace('~^post: ~', '', $array));
// I shuffled the character mask to prove order doesn't matter
var_export(array_map(function($v){return trim($v, ': opst');}, $array));
Output: (from each technique is the same)
array (
0 => '746',
1 => '2',
2 => '84',
)
p.s. If anyone is going to entertain the idea of using explode() to create an array of each element then store the second element of the array as the new desired string (and I wouldn't go to such trouble) be sure to:
split on or : (colon, space) or even post: (post, colon, space) because splitting on : (colon only) forces you to tidy up the second element's leading space and
use explode()'s 3rd parameter (limit) and set it to 2 because logically, you don't need more than two elements

how to serilaze and unserialize an array in php

I have an array like this:
$arr = array(
'type' => 'airport ',
'airport' => 'Delhi Indra Gandhi',
'address' => '',
'city' => '',
'postcode' => ''
);
I serialized it and saved it wp database.
$wpdb->insert( 'table_name', serialize($arr), '%s' );
When I am selecting this data in front end it giving me string like this
a:5:{s:4:\"type\";s:7:\"airport\";s:7:\"airport\";s:18:\"Delhi Indra
Gandhi\";s:7:\"address\";s:0:\"\";s:4:\"city\";s:0:\"\";s:8:\"postcode\";s:0:\"\";}
When I am unserializing it , it gives nothing means an empty string.
Kindly help me.
When you unserialize use urldecode and unserialize example:
$str = serialize($arr);
$strenc = urlencode($str);
Unserialize:
$array = unserialize(urldecode($strenc));

Understanding the basics of multidimensional arrays

I am new to using multidimensional arrays with php, I have tried to stay away from them because they confused me, but now the time has come that I put them to good use. I have been trying to understand how they work and I am just not getting it.
What I am trying to do is populate results based on a string compare function, once I find some match to an 'item name', I would like the first slot to contain the 'item name', then I would like to increment the priority slot by 1.
So when when I'm all done populating my array, it is going to have a variety of different company names, each with their respective priority...
I am having trouble understanding how to declare and manipulate the following array:
$matches = array(
'name'=>array('somename'),
'priority'=>array($priority_level++)
);
So, in what you have, your variable $matches will point to a keyed array, the 'name' element of that array will be an indexed array with 1 entry 'somename', there will be a 'priority' entry with a value which is an indexed array with one entry = $priority_level.
I think, instead what you probably want is something like:
$matches[] = array(name => 'somename', $priority => $priority_level++);
That way, $matches is an indexed array, where each index holds a keyed array, so you could address them as:
$matches[0]['name'] and $matches[0]['priority'], which is more logical for most people.
Multi-dimensional arrays are easy. All they are is an array, where the elements are other arrays.
So, you could have 2 separate arrays:
$name = array('somename');
$priority = array(1);
Or you can have an array that has these 2 arrays as elements:
$matches = array(
'name' => array('somename'),
'priority' => array(1)
);
So, using $matches['name'] would be the same as using $name, they are both arrays, just stored differently.
echo $name[0]; //'somename';
echo $matches['name'][0]; //'somename';
So, to add another name to the $matches array, you can do this:
$matches['name'][] = 'Another Name';
$matches['priority'][] = 2;
print_r($matches); would output:
Array
(
[name] => Array
(
[0] => somename
[1] => Another Name
)
[priority] => Array
(
[0] => 1
[1] => 2
)
)
In this case, could this be also a solution with a single dimensional array?
$matches = array(
'company_1' => 0,
'company_2' => 0,
);
if (isset($matches['company_1'])) {
++$matches['company_1'];
} else {
$matches['company_1'] = 1;
}
It looks up whether the name is already in the list. If not, it sets an array_key for this value. If it finds an already existing value, it just raises the "priority".
In my opinion, an easier structure to work with would be something more like this one:
$matches = array(
array( 'name' => 'somename', 'priority' => $priority_level_for_this_match ),
array( 'name' => 'someothername', 'priority' => $priority_level_for_that_match )
)
To fill this array, start by making an empty one:
$matches = array();
Then, find all of your matches.
$match = array( 'name' => 'somename', 'priority' => $some_priority );
To add that array to your matches, just slap it on the end:
$matches[] = $match;
Once it's filled, you can easily iterate over it:
foreach($matches as $k => $v) {
// The value in this case is also an array, and can be indexed as such
echo( $v['name'] . ': ' . $v['priority'] . '<br>' );
}
You can also sort the matched arrays according to the priority:
function cmp($a, $b) {
if($a['priority'] == $b['priority'])
return 0;
return ($a['priority'] < $b['priority']) ? -1 : 1;
}
usort($matches, 'cmp');
(Sourced from this answer)
$matches['name'][0] --> 'somename'
$matches['priority'][0] ---> the incremented $priority_level value
Like David said in the comments on the question, it sounds like you're not using the right tool for the job. Try:
$priorities = array();
foreach($companies as $company) {
if (!isset($priorities[$company])) { $priorities[$company] = 0; }
$priorities[$company]++;
}
Then you can access the priorities by checking $priorities['SomeCompanyName'];.

Categories