Convert a comma-separated string of key=value expressions into an associative array
Asked Answered
B

6

22

I have a string like this:

key=value, key2=value2

and I would like to parse it into something like this:

array(
  "key" => "value",
  "key2" => "value2"
)

I could do something like

$parts = explode(",", $string)
$parts = array_map("trim", $parts);
foreach($parts as $currentPart)
{
    list($key, $value) = explode("=", $currentPart);
    $keyValues[$key] = $value;
}

But this seems ridiciulous. There must be some way to do this smarter with PHP right?

Basilisk answered 7/2, 2011 at 16:51 Comment(1)
Where does your data come from? Do you control how it is stored? Is it supposed to be a human readable (and writable) format?Mounting
I
23

If you don't mind using regex ...

$str = "key=value, key2=value2";
preg_match_all("/([^,= ]+)=([^,= ]+)/", $str, $r); 
$result = array_combine($r[1], $r[2]);
var_dump($result);
Irrupt answered 7/2, 2011 at 16:56 Comment(4)
however... using explode and loop like in the OP example will more than likely prove to be more efficient than using regex to parse it.Furey
You never know that before you benchmark it. It heavily depends on the usage pattern.Irrupt
I just had to use this. You nailed it!Gastrotrich
I have $selectedSoftware = array("AntiVirus ($20)","Norton ($100)"); $n = implode(',',$selectedSoftware); $bool = preg_match_all("/([^,]+) (\$(\d+))/", $n, $matches); and it returns 0 can't figure out why, i tested it here phpliveregex.com/p/by8Adagio
E
14
<?php parse_str(str_replace(", ", "&", "key=value, key2=value2"), $array); ?>
Eckart answered 7/2, 2011 at 16:57 Comment(1)
Beware this breaks if key or value contains an ampersand (&)Domiciliate
F
12

if you change your string to use & instead of , as the delimiter, you can use parse_str()

Furey answered 7/2, 2011 at 16:55 Comment(0)
C
3

If you can change the format of the string to conform to a URL query string (using & instead of ,, among other things, you can use parse_str. Be sure to use the two parameter option.

Condemnation answered 7/2, 2011 at 16:57 Comment(0)
U
1

Here's a single command solution using array_reduce formatted in multple lines for readability:

<?php
$str = "key=value, key2=value2";
$result = array_reduce(
   explode(',', $str), 
   function ($carry, $kvp) {
      list($key, $value)=explode('=', $kvp); 
      $carry[trim($key)]=trim($value); 
      return $carry;
    }, []);

Undeviating answered 24/2, 2021 at 1:26 Comment(0)
F
1

To cover a fringe case not expressed in this question, but expressed by a page closed by this page, you may need to allow key=value expression-separating characters to be part of the values (such as spaces and commas). In this case, use negated lookaheads to ensure the matched value is not actually part of the next key-value expression and use a lookahead to match the delimiting character(s) or the end of the string.

Code: (Demo)

$test = 'key=value, key2=va, lue 2, key3=value3';


preg_match_all("/(\w+)=((?:(?!\w+=.).)+)(?:, ?|$)/", $test, $m); 
var_export(
    array_combine($m[1], $m[2])
);

Output:

array (
  'key' => 'value',
  'key2' => 'va, lue 2',
  'key3' => 'value3',
)
Fremd answered 25/7 at 12:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.