【问题标题】:Convert a list of dot noted strings into an associative array (PHP)将点号字符串列表转换为关联数组 (PHP)
【发布时间】:2016-08-08 06:00:21
【问题描述】:

我有一个字符串列表,每个字符串都包含点表示的值。我想将此列表转换为关联数组,其中点符号的每个段作为适当嵌套级别中的键。最深层次的嵌套应该具有布尔值 true。字符串可以包含的数量或点段没有限制,因此代码需要进行某种递归来实现目标。

输入示例:

[
    'foo.bar',
    'foo.bar.baz',
    'foo.bar.qux',
    'foo.qux',
    'foo.quux',
    'bar.baz',
    'bar.qux',
    'qux.quux',
]

需要的输出:

[
    'foo' => [
        'bar' => [
            'baz' => true,
            'qux' => true,
        ],
        'qux' => true,
        'quux' => true,
    ],
    'bar' => [
        'baz' => true,
        'qux' => true,
    ],
    'qux' => [
        'quux' => true
    ]
]

【问题讨论】:

  • 那么问题出在哪里?或者您只需要我们为您编写代码?
  • 我需要一点逻辑帮助
  • 请发表您的尝试,到目前为止您已经尝试过什么?
  • @JamesMorgan 我们想提供帮助,但是如果您只是下订单而没有向我们展示您的尝试,您会感到很困难。

标签: php arrays multidimensional-array associative-array


【解决方案1】:

foreach 唯一的解决方案。

function convert(array $input)
{
    $r = [];
    foreach ($input as $dotted) {
        $keys = explode('.', $dotted);
        $c = &$r[array_shift($keys)]; 
        foreach ($keys as $key) {
            if (isset($c[$key]) && $c[$key] === true) {
                $c[$key] = [];
            }
            $c = &$c[$key];
        }
        if ($c === null) {
            $c = true;
        }
    }
    return $r;
}
【解决方案2】:

如果你调用你的起始字符串数组$input,下面代码中的$output数组就是你想要的

$input=[...]; //original array
$output=[];   //holds the results;
foreach ($input as $line){
    $keys = explode('.',$line);//break each section into a key
    $val = true;               //holds next value to add to array
    $localArray = [];          //holds the array for this input line
    for($i=count($keys)-1; $i>=0; $i--){ //go through input line in reverse order
        $localArray = [$keys[$i]=>$val]; //store previous value in array
        $val = $localArray;           //store the array we just built. it will be
                                      //the value in the next loop
    }
    $output = array_merge_recursive($output,$localArray);
}

Live demo

【讨论】:

  • $output['foo']['bar'][0] 不应该存在...?
【解决方案3】:

您可以使用指针和一些逻辑来做到这一点。

<?php
$test = [
    'foo.bar',
    'foo.bar.baz',
    'foo.bar.qux',
    'foo.qux',
    'foo.quux',
    'bar.baz',
    'bar.qux',
    'qux.quux',
];

class Test
{
    public $result = [];

    public function check($array){
        foreach ($array as $value) {
            $this->change($value);
        }
    }

    public function change($string)
    {
        $explodedValues = explode('.',$string);

        $pointerVariable = &$this->result;

        foreach ($explodedValues as $explodedValue) {

            if(!is_array($pointerVariable)){
                $pointerVariable = [];
                $pointerVariable[$explodedValue] = true;
                $pointerVariable = &$pointerVariable[$explodedValue];
            } else if(isset($pointerVariable[$explodedValue])){
                $pointerVariable = &$pointerVariable[$explodedValue];
            } else {
                $pointerVariable[$explodedValue] = true;
                $pointerVariable = &$pointerVariable[$explodedValue];
            }

        }
    }
}

$obj = new Test();
$obj->check($test);

print_r($obj->result);

希望这会有所帮助

【讨论】:

    【解决方案4】:
    function convert($aa) {
      $zz = [];
      foreach( $aa as $value ) {
        $bb = explode('.',$value);
        $cc = count($bb);
        for( $ii = 0, $yy = &$zz; $ii < $cc ; $ii++ ) {
          $key = $bb[$ii];
          if ( array_key_exists($key,$yy) === false || is_array($yy[$key]) === false ) {
            $yy[$key] = [];
          }
          $yy = &$yy[$key];
        }
        $key = $bb[$cc-1];
        if ( array_key_exists($key,$yy) === false ) {
            $yy[$key] = true;
        }
      }
      return $zz;
    }
    

    【讨论】:

    • 如果foo.bar 出现在foo.bar.baz 之后,此代码将中断。在分配 true 之前,您应该检查 $yy[$bb[$cc-1]] 值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 2019-06-26
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    相关资源
    最近更新 更多