【问题标题】:how to convert string to array in php?如何在php中将字符串转换为数组?
【发布时间】:2011-03-18 10:34:54
【问题描述】:

我有这个字符串:

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

我想要这个数组结构:

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

【问题讨论】:

标签: php arrays string


【解决方案1】:

现在parse_url 不适用于您的情况,因为它会覆盖重复的条目。您必须在此处手动提取和分组。

$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;
    }
}

诀窍是注意分隔组的数字键(无值)。循环将生成以下嵌套数组:

[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
    )

【讨论】:

  • @00001:酷。感谢您的反馈!请不要忘记用 ✔ 复选标记标记 my 或 Jon`s 或 ReturnTrue 的答案。
  • 任何真正专业的 PHP 工程师都会告诉你,有太多没有经验的开发人员以非常低劣的方式重新实现轮子。这里真正的教训是教 00001 关于 parse_str() 并让他稍微改变他的输出格式(我们必须假设这是在他的直接操作下)。创建更复杂的 hack 来解决已经解决的问题只是在扩散旧的反模式。
  • @Theodore R. Smith。你的假设是错误的。 (与专业相反)。更改问题域或分配以适应愚蠢的解决方案并不能完全解决问题。 OP 有两个这样的答案可供选择,但没有。您的骇人听闻的解决方案或您对反模式的未经证实的咆哮确实解决了实际上提出的问题。
  • @mario - 所以假设你正在运行一个有 3 个企业消费者的 Web 服务。第四个客户过来说:“我们不想遵守您仔细记录的 XML API。我们的方法就像……”。您是否会自动 a) 建议客户端尝试使用您的 API,可能是通过适配器模式,b) 更改您现有的 API 并且必须重新设计您的其他客户端?你说你会做B)。这不合逻辑。
  • @Theodore:这是真的。然而,我会尽可能让 API 易于使用;以适应其他语言。 (URL 参数中的数组语法对 PHP 来说有点独特,在其他地方也不是什么大问题)。作为最后的手段,一个小的 $_GET 重写包装器(甚至可能通过 .htaccess)将是适用的。 -- 请注意,OP 案例与 URL 无关。正如他后来的一个问题所揭示的那样,他阅读了一种非常无聊的文件交换格式。
【解决方案2】:

您无法使用 $_GET['user'] 发送的标头实现您想要的结果,因为 $_GET['user'] 将是 7(以前的标头将被覆盖。您需要像这样的查询字符串才能走这条路。 .

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

如果您将其作为查询字符串,则使用 array_push 是一个简单的情况,否则您将不得不手动解析字符串 - 再次使用 array_push 生成子数组,然后将它们推送到父数组中。

【讨论】:

    【解决方案3】:

    我很乐意提供帮助!

    <?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
                    )
    
            )
    
    )
    

    由于重新解析错误的输入字符串比回答核心问题要困难得多,因此如果您也需要这方面的帮助,请考虑为其打开一个新问题。

    【讨论】:

    • -1:OP 要求完全不同的东西。在投票之前,请仔细阅读,人们。
    • 实际上我使用 '=' 和 '&' 将二维数组的输出作为字符串......所以我得到了这样的输出......我再次想要那个字符串返回原始数组.....
    • parse_str() 比任何 while 循环都好得多。只需尝试在任何网站上的任何可观数据量,甚至是边缘流量水平。
    • -1 编造微优化借口,否决其他人,以及复制其他参与者的答案想法,但没有注明出处。
    • @mario +1 感谢您有礼貌地表达您的意见。我希望更多的人像你自己一样诚实和勇敢,真的。
    【解决方案4】:

    这是一个没有正则表达式的解决方案。我会觉得更舒服。

    $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.

    【讨论】:

    • 循环中的 PHP 字符串函数几乎总是比正则表达式慢。 :/ -- strspn 行看起来很有趣。你能解释一下它的作用/它是如何工作的吗? (从未见过这样的结构。)
    • @mario:我没有测量过,但我希望在性能方面正好相反。 strspn (php.net/manual/en/function.strspn.php) 条件在这里所做的是检查$item 中除最后一个之外的所有字符是否为数字。这匹配 0=1= 等,并表示我们遇到了新的结果项。
    • @Jon: 想赌 :} 20 美分吗? (我经常测量,我可以保证 PCRE 在这里也表现出色。并不是说这应该是决定因素)。 ——无论如何,谢谢你的解释。并且 +1,因为您的解决方案看起来也正确。
    • @mario: 什么鬼 :) 我的基准在这里:ideone.com/b88tG(每种方法 3 次 x 100K 迭代)。我的机器上的结果(以秒为单位):no regex:2.251982 2.24632 2.245951 with regex:2.670076 2.674494 2.667474。你欠我 20c ;)
    • @Jon。哇,很酷的测试脚本。为此,我一个人就欠你 20 美分。然而,结果几乎被 ideone 歪曲了。这些在线测试工具在旧的 PHP 和 libPCRE 版本以及某种沙箱中运行。我在 php 5.3 amd64 上有当前 pcre 8.12,我的结果是 11.082897 vs 6.763827 for regex ;P -- 但我现在要在真实服务器上测试它......
    【解决方案5】:
    $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);
    

    【讨论】:

      【解决方案6】:

      尝试在表单中编辑您的输入/文本区域 从name="task" 进入 name="data[task]"

      然后你会在var_dump($_GET)看到你的数据

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-26
        • 2011-07-25
        • 1970-01-01
        • 1970-01-01
        • 2012-04-16
        • 1970-01-01
        相关资源
        最近更新 更多