3

I have this string :

0=&task=rose&duration=1.25&user=15&1=&task=daisy&duration=0.75&user=25&2=&task=orchid&duration=1.15&user=7

I want this array structure :

array(
    array( "task" => "rose", 
           "duration" => 1.25,
           "user" => 15 
         ),
    array( "task" => "daisy", 
           "duration" => 0.75,
           "user" => 25,
         ),
    array( "task" => "orchid", 
           "duration" => 1.15,
           "user" => 7 
         )
      )
2
  • 1
    is that the query string of a url? If so, check the $_GET associative array. Commented Mar 18, 2011 at 10:37
  • I think this should answer your question: stackoverflow.com/questions/3533100/… Commented Mar 18, 2011 at 10:40

6 Answers 6

2

Now parse_url won't work for your case, as it will overwrite the duplicate entries. You have to manually extract and group here.

$str = 'decoded_name=0=&task=rose&duration=1.25&user=15&1=&task=daisy&duration=0.75&user=25&2=&task=orchid&duration=1.15&user=7';
preg_match_all('#(\w+)=([^&=]*)(?:&|$)#', $str, $matches, PREG_SET_ORDER); 

$result = array();
$i = 0;    
foreach ($matches as $m) {
    list(, $key, $value) = $m;

    if (!strlen($value)) { 
       $i = (int)$key;
    }
    else {
       $result[$i][$key] = $value;
    }
}

The trick is watching out for the numeric keys (sans value), which separate your groups. The loop will generate following nested array:

[0] => Array
    (
        [task] => rose
        [duration] => 1.25
        [user] => 15
    )

[1] => Array
    (
        [task] => daisy
        [duration] => 0.75
        [user] => 25
    )

[2] => Array
    (
        [task] => orchid
        [duration] => 1.15
        [user] => 7
    )
Sign up to request clarification or add additional context in comments.

5 Comments

@00001: Cool. Thanks for the feedback! Please don't forget to mark either my or Jon`s or ReturnTrue's answer with the ✔ checkmark.
Any truly professional PHP engineer will tell you that there are far too many inexperienced devs reimplementing the wheel in grossly inferior ways. The real lesson here is to teach 00001 about parse_str() and have him marginally change the format of his output (which we must assume is under his direct manipulation). Creating even more complicated hacks to solve already-solved problems is just proliferating old anti-patterns.
@Theodore R. Smith. Your assumption is wrong. (Which is the opposite of professional). Changing the problem domain or assignment to suit the dumb solution doesn't quite cut it. OP had two such answers to pick from, but did not. Your hackish solution nor your unsubstantiated rant about anti-patterns does solve the question which was actually asked.
@mario - So pretend you are running a webservice with 3 corporate consumers. A fourth client comes and says, "We don't want to abide by your carefully documented XML API. Our method is like ...". Do you automatically a) advise the client to try to use your API, maybe via an Adapter pattern, b) change your existing API and have to rework ur other clients? You're saying you would do B). That's not logical.
@Theodore: That's a true point. Yet, I would make the API as easy to use as possible to begin with; to accomodate other languages. (Array syntax in URL params is kinda unique to PHP, and not a big issue elsewhere). As last resort, a small $_GET rewrite wrapper (probably even via .htaccess) would be applicable. -- Note that OPs case is not about URLs though. He reads a very borked file exchange format, as a later question of him revealed.
1

you can't achieve what you want to using the headers send as $_GET['user'] would be 7 (the previous ones would be overwritten. You would need a query string like so to go down that route...

decoded_name=0=&task[]=rose&duration[]=1.25&user[]=15&1=&task[]=daisy&duration[]=0.75&user[]=25&2=&task[]=orchid&duration[]=1.15&user[]=7

if you had that as your query string it would a simple case of using array_push otherwise you will have to parse the string manually - again using array_push to generate the sub arrays and then push those into the parent.

Comments

1

I'm happy to help!

<?php

$input = 'data[0][task]=rose&data[0][duration]=1.25&data[0][user]=15&' .
         'data[1][task]=daisy&data[1][duration]=0.75&data[1][user]=25&' .
         'data[2][task]=orchid&data[2][duration]=1.15&data[2][user]=7';

$output = array();

parse_str($input, $output);

print_r($output);

hopeseekr@7250MHz ~ $ php stack_5350749.php
Array
(
    [data] => Array
        (
            [0] => Array
                (
                    [task] => rose
                    [duration] => 1.25
                    [user] => 15
                )

            [1] => Array
                (
                    [task] => daisy
                    [duration] => 0.75
                    [user] => 25
                )

            [2] => Array
                (
                    [task] => orchid
                    [duration] => 1.15
                    [user] => 7
                )

        )

)

Since reparsing your bad input string would be substantially harder than answering your core question, if you want help with that as well, consider opening a new question for it.

5 Comments

-1: The OP asked for something totally different. Please read a little more carefully before upvoting, people.
actually i used '=' and '&' for getting the output of 2 dimensional array as string....so i am getting output like that......I want again that string back as original array.....
parse_str() scales far better than any while loop. Just try that with any sizable amount of data on any site with even marginal levels of traffic.
-1 For making up microoptimization excuses, downvoting other people, and copying answer idea from another participant sans attribution.
@mario +1 for you for being courteous enough to express your opinion. I wish more were as honest and brave as yourself, truly.
0

Here is a solution without regular expressions. I 'd feel more comfortable with it.

$str = 'decoded_name=0=&task=rose&duration=1.25&user=15&1=&task=daisy&duration=0.75&user=25&2=&task=orchid&duration=1.15&user=7';

// Get rid of "decoded_name", which we don't need
$str = str_replace('decoded_name=', '', $str);

$arr = explode('&', $str);
array_push($arr, '0='); // Add sentinel value to simplify the loop
$results = array();
$parsing = array();

foreach ($arr as $item) {
    // If a new task begins
    if (strspn($item, '0123456789') == strlen($item) - 1) {
        // Add the current item if there is one
        if (!empty($parsing)) {
            $results[] = $parsing;
        }

        // Prepare to parse another item
        $parsing = array();
        continue;
    }

    // Add data to the current item    
    list($key, $value) = explode('=', $item);
    $parsing[$key] = $value;
}

See it in action here.

9 Comments

PHP string functions in loops are almost always slower than regexpressions though. :/ -- The strspn line looks pretty interesting. Can you explain what it does / how it works? (Never seen such a construct.)
@mario: I haven't measured, but I expect the opposite here performance-wise. What the strspn (php.net/manual/en/function.strspn.php) condition does here is check that all of the characters in $item except the last one are digits. This matches 0=, 1=, etc and signals that we have encountered a new result item.
@Jon: Wanna bet :} 20 cent? (I'm measuring that often, I can guarantee that PCRE outperforms here too. Not that this should be a deciding factor). -- Anyway, thanks for the explanation. And +1 because your solution looks correct too.
@mario: What the heck :) My benchmark is here: ideone.com/b88tG (3 times x 100K iterations for each method). Results (in seconds) on my machine: no regex: 2.251982 2.24632 2.245951 with regex: 2.670076 2.674494 2.667474. You owe me 20c ;)
@Jon. Wow, cool test script. I owe you 20¢ alone for that. However the results are pretty much skewed by ideone. These online test tools run on old PHPs and libPCRE versions and in some kind of sandbox. I have the current pcre 8.12 on php 5.3 amd64, and my results are 11.082897 vs 6.763827 for regex ;P -- But I'm going to test it on a real server now...
|
0
$str = "decoded_name=0=&task=rose&duration=1.25&user=15&1=&task=daisy&duration=0.75&user=25&2=&task=orchid&duration=1.15&user=7";

$str = preg_replace("/&\d=/", "", $str);
$str = preg_replace("/&/", "=", $str);
$tmp = preg_split("/=+/", $str);

$length = count($tmp);

for ($i = 2, $j = 0; $i < $length; $i+=6, $j++) {
    $arr[$j] = array($tmp[$i] => $tmp[$i + 1], $tmp[$i + 2] => $tmp[$i + 3], $tmp[$i + 4] => $tmp[$i + 5]);
}

print_r($arr);

Comments

0

Try to edit your input / textarea in your form from name="task" into name="data[task]"

then you will see your data in var_dump($_GET)

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.