PHP - 基于字符串行的嵌套数组键

时间:2013-04-30 16:13:07

标签: php arrays json nested

我需要帮助。我正在寻找这个问题的解决方案! 我有一个包含以下模式的文件:

  

巴西| SaoPaulo | Diadema | RuadaFe巴西|圣保罗| Diadema | RuadoLimoeiro   巴西| SaoPaulo | SaoCaetano | RuadasLaranjeiras   巴西|帕拉纳|库里提巴| ComendadorAraujo   美国|新泽西州|泽西市| WhashingtonBoulervard   美国|新泽西州|泽西市| RiverCourt

在一些数组键实现之后应该带来这样的东西(在php上应用json_encode调用之后):

{
    "name": "Brazil",
    "children": [
    {
        "name": "SaoPaulo",
        "children": [
            {
                "name": "Diadema",
                "children": [
                    {"name": "RuadaFe"},
                    {"name": "RuadoLimoeiro"}
                ]
            },
            {
                "name": "SaoCaetano",
                "children": [
                    {"name": "RuadasLaranjeiras"}
                ]
            },
        ]
        "name": "Parana",
        "children": [
            {
                "name": "Curitiba",
                "children": [
                    {"name": "ComendadorAraujo"}
                ]
            }
       ]
    },
    "name":"USA",
    "children":[
      {
         "name": "NewJersey",
          "children": [
            {
                "name": "JerseyCity",
                "children": [
                    {"name": "WhashingonBoulevard"},
                    {"name": "RiverCourt"}
                ]
            }
          ]
       }
     ]
  }
 ]

继续前进(甚至更深)。 请帮助我团队......提前谢谢。

这是我到现在为止所得到的:

阵 (     [巴西] =>排列         (             [SaoPaulo] =>排列                 (                     [Diadema] =>排列                         (                             [RuadoLimoeiro] =>                         )

                [SaoCaetano] => Array
                    (
                        [RuadasLaranjeiras] => 
                    )

            )

        [Parana] => Array
            (
                [Curitiba] => Array
                    (
                        [ComendadorAraujo] => 
                    )

            )

    )

[USA] => Array
    (
        [NewJersey] => Array
            (
                [JerseyCity] => Array
                    (
                        [WhashingtonBoulervard] => 
                        [RiverCourt] => 
                    )

            )

    )

以下是json编码:

{
"Brazil":{
"SaoPaulo":
   {"Diadema":
       {"RuadoLimoeiro":null},
       "SaoCaetano":{"RuadasLaranjeiras":null}
       },
"Parana":
   {"Curitiba":
       {"ComendadorAraujo":null}
   }
},
"USA":{
"NewJersey":{
"JerseyCity":{
     "WhashingtonBoulervard":null,
     "RiverCourt":null}
      }
    }
}

正如你所看到的,“names”和“child”缺失,因为它不是数组键结构,也有问题,因为我在SaoPaulo上缺少一些值。

这是功能:

foreach($strings as $string) {
    $parts = array_filter(explode('|', $string));
    $ref = &$result;
    foreach($parts as $p) {
       // echo $p;
        if(!isset($ref[$p])) {
            $ref[$p] = array();
           // $ref[$p] = array("name"=>$p);
        }

        $ref = &$ref[$p];

    }
    $ref = null;
}

--------------------------------有些回答------------ --------------

{
    "name": "Brazil(country)",
    "children": [
    {
        "name": "SaoPaulo(state)", // only one state
        "children": [
            {
                "name": "Diadema(city)", // only one city
                "children": [
                    {"name": "RuadaFe(street)"}, // two streets under the same city...
                    {"name": "RuadoLimoeiro(street)"}
                ]
            },
            {
                "name": "SaoCaetano(city)",
                "children": [
                    {"name": "RuadasLaranjeiras(street)"}
                ]
            },
        ]
        "name": "Parana(state)",
        "children": [
            {
                "name": "Curitiba(city)",
                "children": [
                    {"name": "ComendadorAraujo(street)"}
                ]
            }
       ]
    },...

我把结构(国家,州,城市,街道)放在肠胃外只是为了澄清我想要的东西。 知道了吗?

2 个答案:

答案 0 :(得分:0)

它能解决您的问题吗?使用$inputString放置真正的字符串。

    <?php

// ------------------------------------------------------ your input goes here ------------------------------------------------------
$inputString = 'Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras Brazil|Parana|Curitiba|ComendadorAraujo USA|NewJersey|JerseyCity|WhashingtonBoulervard USA|NewJersey|JerseyCity|RiverCourt';

class item {
    public $name = null;

    public function getChildrenByName($strName) {

        $ret = null;
        # this variable should be defined in interface, but i skipped it so it wont be printed in json when obj does not have childrens
        if( !isset( $this->children ) ) {
            $this->children = array(  );
        }

        foreach ( $this->children as $child ) {
            if( $child->name === $strName ) {
                $ret = $child;
                break;
            }
        }


        if ( !$ret ) {
            $this->children[] = self::spawnByName( $strName );
        }

        return $this->children[ count($this->children) - 1];
    }

    static public function spawnByName($strName) {
        $ret = new item();
        $ret->name = $strName;
        return $ret;
    }
}

class listManager {

    protected $list = array();

    public function getList() {
        return $this->list;
    }

    public function addPath( $desiredPath ) {

        # path needs to be as array
        if ( is_string( $desiredPath ) ) {
            $desiredPath = explode('|', $desiredPath);
        }

        # create root element if it does not already exists
        if ( !isset( $this->list[$desiredPath[0]] ) ) {
            $this->list[$desiredPath[0]] = item::spawnByName($desiredPath[0]);
        }

        $curElement = $this->list[$desiredPath[0]];

        for( $i=1; $i<count($desiredPath); $i++ ) {
            $curElement = $curElement->getChildrenByName( $desiredPath[$i] );
        }

    }

    protected function spawnElement( $strName ) {
        $ret = new item();
        $ret->name = $strName;
        return $ret;
    }
}

$output = array();
$expl = explode(' ', $inputString);
$list = new listManager();

foreach ( $expl as $key => $path ) {
    $list->addPath( $path );

}

$output = '';

foreach ( $list->getList() as $singleVariable ) {
    $output .= json_encode($singleVariable, JSON_PRETTY_PRINT) . ",\n";
}

echo '<pre>'.$output.'</pre>';

?>

上面的代码会从您的示例代码中生成以下json:

{
    "name": "Brazil",
    "children": [{
            "name": "SaoPaulo",
            "children": [{
                    "name": "Diadema",
                    "children": [{
                            "name": "RuadaFe"
                        }
                    ]
                }
            ]
        }, {
            "name": "SaoPaulo",
            "children": [{
                    "name": "Diadema",
                    "children": [{
                            "name": "RuadoLimoeiro"
                        }
                    ]
                }
            ]
        }, {
            "name": "SaoPaulo",
            "children": [{
                    "name": "SaoCaetano",
                    "children": [{
                            "name": "RuadasLaranjeiras"
                        }
                    ]
                }
            ]
        }, {
            "name": "Parana",
            "children": [{
                    "name": "Curitiba",
                    "children": [{
                            "name": "ComendadorAraujo"
                        }
                    ]
                }
            ]
        }
    ]
} {
    "name": "USA",
    "children": [{
            "name": "NewJersey",
            "children": [{
                    "name": "JerseyCity",
                    "children": [{
                            "name": "WhashingtonBoulervard"
                        }
                    ]
                }
            ]
        }, {
            "name": "NewJersey",
            "children": [{
                    "name": "JerseyCity",
                    "children": [{
                            "name": "RiverCourt"
                        }
                    ]
                }
            ]
        }
    ]
}

编辑已更改,现在适合吗?

答案 1 :(得分:0)

这不是完全无足轻重的,但我所做的实际上和你一样(与你编辑的问题中的方式相同),但我也跟踪那些重命名键的数组。那就是我之后做的事情:

$separator = [' ', '|'];

$buffer = file_get_contents($file);
$entries = explode($separator[0], $buffer);
$result = [];
$named[] = &$result;
########
foreach ($entries as $entry) {
    $each     = explode($separator[1], $entry);
    $pointer  = & $result;
    while ($current = array_shift($each)) {
        if (!isset($pointer[$current])) {
            unset($children);
            $children = [];
            $named[] = &$children;
            ########
            $pointer[$current] = ['name' => $current, 'children' => &$children];
        }
        $pointer = & $pointer[$current]['children'];
    }
}

foreach($named as $offset => $namedArray) {
    $keys = array_keys($namedArray);
    foreach($keys as $key) {
        $named[$offset][] = &$namedArray[$key];
        unset($named[$offset][$key]);
    }
}

print_r($result);

See it in action.

你可能可能希望通过检查以后的foreach是否为空(叶子节点)然后删除子条目来修改它。

这里修改了foreach的结尾和json输出:

foreach($named as $offset => $namedArray) {
    $keys = array_keys($namedArray);
    foreach($keys as $key) {
        if (!$namedArray[$key]['children']) {
            unset($namedArray[$key]['children']);
        }
        $named[$offset][] = &$namedArray[$key];
        unset($named[$offset][$key]);
    }
}

echo json_encode($result, JSON_PRETTY_PRINT);

输出:

[
    {
        "name": "Brazil",
        "children": [
            {
                "name": "SaoPaulo",
                "children": [
                    {
                        "name": "Diadema",
                        "children": [
                            {
                                "name": "RuadaFe"
                            },
                            {
                                "name": "RuadoLimoeiro"
                            }
                        ]
                    },
                    {
                        "name": "SaoCaetano",
                        "children": [
                            {
                                "name": "RuadasLaranjeiras"
                            }
                        ]
                    }
                ]
            },
            {
                "name": "Parana",
                "children": [
                    {
                        "name": "Curitiba",
                        "children": [
                            {
                                "name": "ComendadorAraujo"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "name": "USA",
        "children": [
            {
                "name": "NewJersey",
                "children": [
                    {
                        "name": "JerseyCity",
                        "children": [
                            {
                                "name": "WhashingtonBoulervard"
                            },
                            {
                                "name": "RiverCourt"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

完整的代码示例一目了然:

<?php
/**
 * PHP - Nested array keys based on string lines
 * @link http://stackoverflow.com/a/16305236/2261774
 */
$file = 'data://text/plain;base64,' . base64_encode('Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras Brazil|Parana|Curitiba|ComendadorAraujo USA|NewJersey|JerseyCity|WhashingtonBoulervard USA|NewJersey|JerseyCity|RiverCourt');

$separator = [' ', '|'];

$buffer = file_get_contents($file);
$entries = explode($separator[0], $buffer);
$result = [];
$named[] = &$result;
foreach ($entries as $entry) {
    $each     = explode($separator[1], $entry);
    $pointer  = & $result;
    while ($current = array_shift($each)) {
        if (!isset($pointer[$current])) {
            unset($children);
            $children = [];
            $named[] = &$children;
            $pointer[$current] = ['name' => $current, 'children' => &$children];
        }
        $pointer = & $pointer[$current]['children'];
    }
}
unset($pointer);

foreach($named as $offset => $namedArray) {
    $keys = array_keys($namedArray);
    foreach($keys as $key) {
        if (!$namedArray[$key]['children']) {
            unset($namedArray[$key]['children']);
        }
        $named[$offset][] = &$namedArray[$key];
        unset($named[$offset][$key]);
    }
}
unset($named);

echo json_encode($result, JSON_PRETTY_PRINT);

你的问题JSON:

{
    "name": "Brazil",
    "children": [
    {
        "name": "SaoPaulo",
        "children": [
            {
                "name": "Diadema",
                "children": [
                    {"name": "RuadaFe"},
                    {"name": "RuadoLimoeiro"}
                ]
            },

我的回答JSON:

[
    {
        "name": "Brazil",
        "children": [
            {
                "name": "SaoPaulo",
                "children": [
                    {
                        "name": "Diadema",
                        "children": [
                            {
                                "name": "RuadaFe"
                            },
                            {
                                "name": "RuadoLimoeiro"
                            }
                        ]
                    },

我能发现的唯一区别是根节点在我的答案中被包装在一个数组中,但是如果真的是你的问题那么将它们提取到那里应该是微不足道的;)