将PHP字符串转换为嵌套/多维数组

3
我有一个php字符串示例: $string = "@[item_1][door] @[mozart][grass] = yes @[mozart][green] = no @[mozart][human] @[blue][movie]=yes @[item_1][beat] = yes @[item_1][music] = no";
现在将$string缩进以便于查看:
@[item_1][door] @[mozart][grass] = yes @[mozart][green] = no @[mozart][human]
@[blue][movie]=yes
@[item_1][beat] = yes @[item_1][music] = no
我想知道如何获取此类字符串(或其他遵循此样式的字符串)并将其转换为以下数组:
Array
(
    [item_1] => Array
        (
            [door] => Array
                (
                    [mozart] => Array
                        (
                            [grass] => yes
                            [green] => no
                            [human] => Array
                                (
                                    [blue] => Array
                                        (
                                            [movie] => yes
                                        )
                                )
                        )
                )
            [beat] => yes
            [music] => no
        )
)

我的尝试

我试图使用递归函数创建一个嵌套数组,但是在递归函数中我无法访问数组指针(在深层级别)...不知道为什么...也许这不是正确的答案。谢谢。


你可以展示一下你的递归函数。如果你使用了引用,可能需要保持一个列表,因为你在进出子数组时需要用到它们。 - mario
如何从原始字符串中逻辑地确定蓝色是 Human 中的一个数组?如果您无法定义一个合理简单的规则来确定这一点,编写代码将会很困难甚至不可能。 - Brendon Dugan
为什么不坚持使用XML或JSON? - Niklas Lindblad
你的字符串格式不清晰。例如,第一行是没有缩进的,但是第六行(@[item_1][beat] = yes)却缩进了一个级别。这里没有明确的格式。 - nicktacular
该字符串具有格式,我已经有一个处理它的函数-https://gist.github.com/1553533-现在问题是我正在尝试将其转换为JSON,并且我将在主题上解释一些详细信息。@Mario - Omnia
问题太长了,无法在此发布,请问您能否在这里查看并回复?http://forums.devshed.com/php-development-5/php-string-to-nested-multidimensional-array-873739.html @brendon-dugan - Omnia
1个回答

3

好的,我希望你仍然需要这个,因为我花费了比我想承认的更多的时间来做对这件事:)

基本上,我的方法是先将字符串操作成格式[set][of][keys]=value,然后循环遍历键的字符串,并将它们与上一组键进行比较,以创建正确的键层次结构。我使用eval是因为它更容易,但如果你不能忍受在你的代码中看到那个函数,你可以编写一个替换函数:

//FIRST WE GET THE STRING INTO EASIER TO WORK WITH CHUNKS
$original_string = "@[item_1][door] @[mozart][grass] = yes @[mozart][green] = no @[mozart][human] @[blue][movie]=yes @[item_1][beat] = yes @[item_1][music] = no ";
$cleaned_string = str_replace('] @[','][',$original_string);
/* This results in clusters of keys that equal a value:
@[item_1][door][mozart][grass] = yes @[mozart][green] = no @[mozart][human][blue][movie]=yes @[item_1][beat] = yes @[item_1][music] = no 

OR (with line breaks for clarity):

@[item_1][door][mozart][grass] = yes 
@[mozart][green] = no 
@[mozart][human][blue][movie]=yes 
@[item_1][beat] = yes 
@[item_1][music] = no */

//break it up into an array:
$elements = explode('@',$cleaned_string);

//create a variable to compare the last string to
$last_keys = "";
//and another that will serve as our final array
$array_of_arrays = array();
//now loop through each [item_1][door][mozart][grass] = yes,[mozart][green] = no, etc
foreach($elements as $element){
    if ($element==""){continue;} //skip the first empty item

    //break the string into [0] = group of keys and [1] the value that terminates the string 
    //so [item_1][door][mozart][grass] = yes BECOMES [item_1][door][mozart][grass], AND yes
    $pieces = explode('=',str_replace(array('[',']'),array("['","']"),trim($element))); 
    //now compare this set of keys to the last set of keys, and if they overlap merge them into a single key string
    $clean_keys = combine_key_strings($pieces[0],$last_keys);
    //set the new key string the value for the next comparison
    $last_keys = $clean_keys;
    //and (ugly, I know) we use an eval to convert "[item_1][door][mozart][grass]='yes'" into a properly keyed array
    eval("\$array_of_arrays".$clean_keys." = '".trim($pieces[1])."';");
}

//now dump the contents
print_r($array_of_arrays);


//THIS FUNCTION COMPA
function combine_key_strings($new,$old){
    //get the key that starts the newer string
    $new_keys = explode('][',$new);
    $first_key = $new_keys[0].']';

    //see if it appears in the last string
    $last_occurance = strrpos ($old,$first_key);
    //if so, merge the two strings to create the full array keystring
    if (is_int($last_occurance)){
        return substr($old,0,$last_occurance).$new;
    }
    return $new;
}

这应该可以输出您嵌套正确的数组:
Array
(
    [item_1] => Array
        (
            [door] => Array
                (
                    [mozart] => Array
                        (
                            [grass] => yes
                            [green] => no
                            [human] => Array
                                (
                                    [blue] => Array
                                        (
                                            [movie] => yes
                                        )

                                )

                        )

                )

            [beat] => yes
            [music] => no
        )

)

晚安!


太好了!非常感谢@ben-d!这是一个非常大的问题!很棒的函数!谢谢! - Omnia
请记住我的警告,不要使用eval()函数调用...如果有任何可能数据复制php函数调用的机会(特别是如果任何数据由第三方设置),您可能面临php注入风险,在这种情况下,您需要编写一个自定义函数来处理此过程(生成一个数组并将其递归合并到主数组中)。祝你好运! - Ben D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接