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.. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.