2

I have a string like:

$string = "/key/value/anotherKey/anotherValue/thirdKey/thirdValue"

I would like to parse this string to an array of key => value:

array(
    key => value,
    anotherKey => anotherValue,
    thirdKey => thirdValue
);

The only solution I have found is the following, but it seems that there should be an easier way to achieve my goal:

$split = preg_split("[/]", $string, null, PREG_SPLIT_NO_EMPTY);
$i = 0;
$j = 1;
$array = [];
for(;$i<count($split)-1;){
    $array[$split[$i]] = $split[$j];
    $i += 2;
    $j += 2;
}

I have looked at this SO post, put it only works for query strings like:

"key=value&anotherKey=anotherValue&thirdKey=thirdValue"

Can anyone guide me towards a more "simple" solution (by that I mean less code to write, the usage of PHP functions and I would like to prevent using loops)? Thank you!

7
  • You could reveiew the Zend 1 source and see how they achieve this with Zend_Uri Commented May 18, 2015 at 8:31
  • @skirato i have answered for your question,plz look at that once and let me know. Commented May 18, 2015 at 9:07
  • So where are we with this question ? Commented May 18, 2015 at 9:16
  • 1
    Downvoter, please explain yourself? How can my question be more clear, explained? Commented May 18, 2015 at 9:24
  • 1
    @skirato Too late to party here but I have updated my answer anyway as per your updated question. It does not use loop now. Commented May 18, 2015 at 10:20

5 Answers 5

4

Here is another simply way of achieving this using preg_replace() and parse_str():

$string = '/key/value/anotherKey/anotherValue/thirdKey/thirdValue';

// Transform to the query string (replace '/key/val' by 'key=val&')
$string = trim(preg_replace('|/([^/]+)/([^/]+)|', '$1=$2&', $string), '&');

// Parse the query string into array variable
parse_str($string, $new_array);
print_r($new_array);

Outputs:

Array
(
    [key] => value
    [anotherKey] => anotherValue
    [thirdKey] => thirdValue
)
Sign up to request clarification or add additional context in comments.

Comments

2

This should work for you:

First I explode() the string into an array. Here I make sure to remove slashes at the beginning and at the end of the string with trim(), so I don't get empty elements.

After this I just array_filter() all elements out which have an even key as keys and all elements with an odd key as values.

At then end I simply array_combine() the two arrays into one.

<?php

    $string = "/key/value/anotherKey/anotherValue/thirdKey/thirdValue";
    $arr = explode("/", trim($string, "/"));

    $keys = array_filter($arr, function($k){
        return ($k % 2 == 0);
    }, ARRAY_FILTER_USE_KEY);
    $values = array_filter($arr, function($k){
        return ($k % 2 == 1);
    }, ARRAY_FILTER_USE_KEY);

    $result = array_combine($keys, $values);
    print_r($result);

?>

output:

Array
(
    [key] => value
    [anotherKey] => anotherValue
    [thirdKey] => thirdValue
)

Demo

For PHP <5.6, just use a workaround with array_flip(), since you can't use the flags from array_filter():

Demo

4 Comments

Thanks for your answer I like this logic, but $keys and $values are null for me...
@skirato What is the output of: echo phpversion(); for you?
@skirato Then the problem is, that you can't use the constants from array_filter(), just do a little workaround with array_flip() -> 3v4l.org/AA3F8
Nice, only thing you should have minimum PHP 5.6.0 for 3rd argument ARRAY_FILTER_USE_KEY
1

explode it and generate the array by looping through it. Hope this could help -

$string = "/key/value/anotherKey/anotherValue/thirdKey/thirdValue";

$vars = explode('/', $string);

$i = 0;
$newArray = array();
while ($i < count($vars)) {
   if (!empty($vars[$i])) {
     $newArray[$vars[$i]] = $vars[$i+1];
     $i += 2;
   } else {
     $i++;
   }
}

Output

array(3) {
  ["key"]=>
  string(5) "value"
  ["anotherKey"]=>
  string(12) "anotherValue"
  ["thirdKey"]=>
  string(10) "thirdValue"
}

1 Comment

Thanks for your answer. The only simplification I see is the fact that you use only one index variable instead of two, which is indeed better. But explode doesn't allow to remove empty values, so you have to use an if/else. For that, I do prefer my preg_split with the NO_EMPTY flag. I was wondering if there wasn't a way to simplify this much more (but maybe there isn't...)
1

You can also try like this

 [akshay@localhost tmp]$ cat test.php
 <?php

 $string = "/key/value/anotherKey/anotherValue/thirdKey/thirdValue";

 $array  = array_flip(explode('/',rtrim(ltrim($string,'/'),'/')));

 print_r( 
          array_combine(
                        array_flip(array_filter($array,function($v){return (!($v & 1)); })),
                        array_flip(array_filter($array,function($v){return ($v & 1);    })) 
                       )
        );

 ?>

Output

 [akshay@localhost tmp]$ php test.php
 Array
 (
     [key] => value
     [anotherKey] => anotherValue
     [thirdKey] => thirdValue
 )

1 Comment

rtrim(ltrim($string,'/'),'/') = trim($string,' /')
1

This is working like as your requirement: Look at this code once:

<?php
$str = 'key/value/anotherKey/anotherValue/thirdKey/thirdValue';
$list = explode('/', $str);
$result = array();
for ($i=0 ; $i<count($list) ; $i+=2) {
    $result[ $list[$i] ] = $list[$i+1];
}
echo "After Split String".'<pre>';
print_r($result);
echo '</pre>';
?>

Output:-

After Split String
Array
(
    [key] => value
    [anotherKey] => anotherValue
    [thirdKey] => thirdValue
)

For your reference click Demo Example

Comments

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.