Массив преобразования рекурсивный ассоциативный

0

У нас есть массив со следующими значениями:

$a = array("a", "a.b", "a.b.c", "X", "X.Y", "X.Y.Z");

И цель состоит в том, чтобы внести изменения в первый массив в следующую структуру:

$a = array(
     "a" => array(
         "b" => array(
             "c" => array(),
         ),
     ),
     "X" => array(
         "Y" => array(
             "Z" => array(),
         ),
     ),
);

Почему я спрашиваю? У моего клиента есть таблица для категорий магазинов. И эти категории находятся в одной колонке (упрощенной!):

 +-----------------------+
 |id |       name        |
 +---|-------------------+
 | 4 | A                 |
 | 5 | A.B               |
 | 6 | A.B.C             |
 | 7 | X                 |
 | 8 | X.Y               |
 | 9 | X.Y.Z             |
 +-----------------------+

Как я могу это сделать с PHP?

РЕДАКТИРОВАТЬ:

Мое текущее "решение/попытки"

<?php

$arr = array(
    "a",
    "a.b",
    "a.b.c",
    "x",
    "x.y",
    "x.y.z",
);

$container = array();
$updateMe = array();

foreach($arr as $key => $value) {
    $cleanName = explode(".", $value);

    foreach($cleanName as $keyArray => $valueArray) {
        for($c = 0;$c<$keyArray+1;$c++) {
            $updateMe[$cleanName[$c]] = array();
        }


    } 

    $container[$cleanName[0]] = $updateMe;
    unset($updateMe);
}

echo "<pre>";
var_dump($container);
echo "===\r\n";

Мой выход:

array(2) {
  ["a"]=>
  array(3) {
    ["a"]=>
    array(0) {
    }
    ["b"]=>
    array(0) {
    }
    ["c"]=>
    array(0) {
    }
  }
  ["x"]=>
  array(3) {
    ["x"]=>
    array(0) {
    }
    ["y"]=>
    array(0) {
    }
    ["z"]=>
    array(0) {
    }
  }
}
===

РЕШЕНИЕ

<?php

$arr = array(
    "a",
    "a.b",
    "a.b.c",
    "x",
    "x.y",
    "x.y.z",
);

$array = array();
$test = array();

foreach($arr as $key => $text) {
    $array = array();
    foreach(array_reverse(explode('.', $text)) as $key) $array = array($key => $array);

    $test[] = $array;
}

echo "<pre>";
var_dump($test);
echo "===\r\n";
  • 0
    А какой у тебя вопрос?
  • 0
    Ваш массив не имеет смысла!
Показать ещё 11 комментариев
Теги:
arrays

4 ответа

1
Лучший ответ

Вы можете использовать принятый ответ из этого вопроса или этот ответ из того же вопроса, чтобы получить хорошую отправную точку (я буду использовать второй ответ, потому что в этом примере он короче).

$out = array();
foreach ($a as $string) {
    $array = array();
    foreach(array_reverse(explode('.', $string)) as $key) {
        $array = array($key => $array);
    }
    $out[] = $array;
}

Это даст вам массив с числовым ключом, поэтому вы можете перейти от первого уровня массива, используя ответ на этот вопрос:

$out = call_user_func_array('array_merge', $out);

И ваш результат:

Array
(
    [a] => Array
        (
            [b] => Array
                (
                    [c] => Array
                        (
                        )

                )

        )

    [X] => Array
        (
            [Y] => Array
                (
                    [Z] => Array
                        (
                        )

                )

        )

)
  • 0
    Вот фрагмент, который я искал! Большое спасибо!
2

Мне нравится использовать ссылки в PHP. Это может быть не лучшее решение, но, похоже, оно работает.

<?php
$arr = array(
    "a",
    "a.b",
    "a.b.c",
    "x",
    "x.y",
    "x.y.z",
);

$output = array();

foreach($arr as $path){
    // Create a reference to the array
    // As we go deeper into the path we will move this reference down
    $setArray =& $output;

    foreach(explode('.', $path) as $key){
        // If this key does not exist, create it
        if(!isset($setArray[$key])){
            $setArray[$key] = array();
        }

        // Move the reference down one level,
        // so that the next iteration will create
        // the key at the right level
        $setArray =& $setArray[$key];
    }
}

// Destroy the reference, so that we don't accidently write to it later
unset($setArray);

var_dump($output);
  • 2
    Еще один отличный ответ! Преимущество этого решения в том, что внутри массива нет дублированного содержимого / дублированных слоев / элементов!
0

просто сложный

  $a = array("a", "a.b", "a.b.c", "X", "X.Y", "X.Y.Z");

    $res = array();
    foreach ($a as $str) {
        $str = str_replace('.','"]["',$str);
        $tricky = '$res["'.$str.'"]';
        eval ($tricky.' = array();');
};
  • 0
    Использование eval для этого - плохая новость.
0

Это должно сработать для вас:

<?php

    $a = array("a", "a.b", "a.b.c", "1", "1.2", "1.2.3");
    $results = array();

    function stringToArray($path) {

        $pos = strpos($path, ".");

        if ($pos === false)
            return array($path => "");

        $key = substr($path, 0, $pos);
        $path = substr($path, $pos + 1);

        return array(
            $key => stringToArray($path)
        );

    }

    foreach($a as $k => $v) {
        if(substr_count(implode(", ", $a), $v) == 1)
            $results[] = stringToArray($v);
    }

    $results = call_user_func_array('array_merge', $results);
    print_R($results);

?>

Вывод:

Array ( [a] => Array ( [b] => Array ( [c] => ) ) [0] => Array ( [2] => Array ( [3] => ) ) )

Ещё вопросы

Сообщество Overcoder
Наверх
Меню