0

I have strings like var=test;path=test.html

I want to convert these kind of strings like the array printed below :

Array
{
    var  => test
    path => test.html,
}

I tried to use PHP's explode function for this task, but this is converting the string to associative array, and then i decided to convert that associate array to the one shown above.

But my own code isn't what i'm looking for, 'cause it contain 2 times PHP's explode function and some foreach loops, thus my own code will not stand in the department of performance for such a simple task.

Your help will be much appreciated, thanks.

1
  • you need just one foreach.. I don't think there is an easier way Commented Sep 11, 2011 at 21:56

5 Answers 5

6

Use parse_str for this: http://www.php.net/manual/en/function.parse-str.php

Sign up to request clarification or add additional context in comments.

3 Comments

The problem is, he is using ';' as the variables separator, but parse_str expects them to be separated by &. There should be a php.ini setting for that, so he should be able to change that with some ini_get -> ini_set -> restore '&' ini_set, but it doesn't look like a very good solution for that..
at that link i found this function : ` function parseQueryString($str) { $op = array(); $pairs = explode("&", $str); foreach ($pairs as $pair) { list($k, $v) = array_map("urldecode", explode("=", $pair)); $op[$k] = $v; } return $op; }` that's why i call it a great link :)
=> I just fixed the 'explode on ;' issue, and performed a performance comparison on the two functions: see below my updated answer.
3

You could explode by semicolon, then explode by =, and then use array_combine().


The solution is really not all that pretty, since it's quite verbose. I typed it out just in case, but you're probably better off with another method.

$s = "var=test;path=test.html";

$b = array_map(function($x){return explode("=", $x); }, explode(";", $s));
$c1 = array_map(function($x){return $x[0]; }, $b);
$c2 = array_map(function($x){return $x[1]; }, $b);

$result = array_combine($c1, $c2);

Comments

1

You could use preg_match_all to get an array of keys, and an array of values, then combine them into an associative array using array_combine:

$str = "var=test;path=test.html";
preg_match_all("/([^;=]+)=([^;=]+)/", $str, $matches);
$result = array_combine($matches[1], $matches[2]);

1 Comment

Do you realize that regular expressions, although they look good and clean, are the most inefficient thing ever in most cases of simple string parsing/splitting?
1

I just figured out how you can do that by using the parse_str php built-in function.

From the php.ini documentation:

; List of separator(s) used by PHP to parse input URLs into variables.
; PHP's default setting is "&".
; NOTE: Every character in this directive is considered as separator!
; http://php.net/arg-separator.input
; Example:
;arg_separator.input = ";&"

So, if you do this:

ini_set('arg_separator.input', ';&');

The parse_str should explode query arguments both on ; and &. This shouldn't affect in any way the filling of $_GET and $_POST since they are loaded before your code execution. If you want to be sure you don't affect the behavior of any other function calling parse_str, you could use a function like this:

function my_parse_str($str, &$arr) {
    $orig = ini_get('arg_separator.input');
    ini_set('arg_separator.input', ';');
    parse_str($str, $arr);
    ini_set('arg_separator.input', $orig);
}

Two advantages over exploding on & and then on =:

  1. Maximum execution speed since the parse_str() function is built-in
  2. parse_str() also considers recursive splitting: a=1&a=2 -> array('a'=>array('1', '2')); or 'a[one]=1&a[two]=2' -> array('a'=>array('one'=>'1', 'two'=>'2')).

Update - performance benchmarking

I just run a test to compare the plain-php splitting vs parse_str(), on an array of 10000 query strings each made of 500 arguments. The my_parse_str() above took ~0.952 seconds, while the pure-php one (parseQueryString()) took ~4.25 seconds.

It would require a larger set of data to test exactly how much it is faster, but it's pretty clear which one wins :) (if you want the test data + scripts, I'll upload them somewhere, since the data file is 125MB).

4 Comments

pointless benchmarking and useless function instead of just str_replace.
thanks redShadow, can you upload your test and benchmarking data somewhere? :)
1. I did a benchmarking test since he asked for something that "stands in the department of performance"; 2. What do you mean by "just str_replace"? I see no way to do that with a str_replace, plus, the correct way to parse a query string is to use the built-in function parse_str.
@Ranbir I uploaded the benchmark scripts here: stuff.hackzine.org/misc/querystring-parsing-benchmark You don't need to regenerate input.php (it takes quite a long time to generate all that random strings), just rename the scripts from .php.txt to plain .php and run them on the console. I added a third benchmark script "regexp.php" to test the answer using preg_match_all().. it took 11 seconds
0

How about str_replace?

$text = "var=test;path=test.html";
$text = str_replace(';',"\n\t", $text);
$text = str_replace('='," => ", $text);
echo <<<END
Array
{
\t$text
}
END;

You'll need to do some extra work to get the proper formatting, though

2 Comments

I think you misinterpreted the output text in Ranbir Kapoor's question as a string. I believe he wants the output to be in the form of an associative array.
..of course you could then eval() that but yes, I guess (and hope) you misinterpreted the output text in the question.. :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.