2016-08-08 12 views
0

それぞれにドット表記の値を含む文字列のリストがあります。私はこのリストを適切なネストレベルのキーとしてドット表記の各セグメントを持つ連想配列に変換したいと思います。ネストの最も深いレベルは、ブール値trueを持つ必要があります。文字列に含めることができる数字やドットのセグメントに制限はありませんので、目標を達成するために何らかの再帰を行う必要があります。ドット付きの文字列のリストを連想配列に変換する(PHP)

入力例:

[ 
    '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 
    ] 
] 
+2

だから何が問題なのですか?あるいは、コードを書くだけでいいのですか? – Sejanus

+0

私は論理に少し助けが必要です –

+0

これまでに試したことを投稿してください。 –

答えて

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; 
} 
+0

提案:[ドット連鎖表記で配列要素を取得/設定/解除する](http://qiita.com/mpyw/items/185c00306b7d7d6a06d0) – mpyw

+0

迅速な回答をいただきありがとうございます。問題が解決しました! –

0

あなたは、文字列$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

+0

'$ output ['foo'] ['bar'] [0]'存在すべきではない...? – mpyw

0
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; 
} 
+1

このコードは 'foo.bar.baz'の後に' foo.bar'が現れたときに破損します。 trueを代入する前に、 '$ yy [$ bb [$ cc-1]]'の値をチェックする必要があります。 – mpyw

0

これは、ポインタとロジックを使用して行うことができます。

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

これは

関連する問題