2016-12-02 5 views
0

Я пытаюсь построить древовидную карту из категорий.Дерево по категориям

У меня есть категории (у меня есть много категорий, и я хочу, чтобы удалить дубликаты и показать их в виде дерева-карты)

$cat = array(
    "Sneakers/Men", 
    "Sneakers/Women", 
    "Accessories/Jewellery/Men", 
    "Accessories/Jewellery/Women", 
    "Accessories/Jewellery/Men 
"); 

... и я хочу, чтобы они, как этот

$categories = array(
    "Sneakers" => array(
     "Men" => array(), 
     "Women" => array() 
    ), 
    "Accessories" => array(
     "Jewellery" => array(
      "Men" => array(), 
      "Women" => array() 
     ) 
    ) 
); 

печатать их, как этот

- Sneakers 
-- Men 
-- Women 

- Accessories 
-- Jewellery 
--- Men 
--- Women 

ответ

2

Попробуйте это:

<?php 
$cat = array(
    "Sneakers/Men", 
    "Sneakers/Women", 
    "Accessories/Jewellery/Men", 
    "Accessories/Jewellery/Women", 
    "Accessories/Jewellery/Men 
"); 

function buildTree($categories, $result = []){ 
    $temp = []; 
    foreach($categories as $categoryString){ 
     $catParts = explode('/',$categoryString); 
     if(count($catParts) > 1){ 
      $temp[$catParts[0]][] = str_replace($catParts[0].'/','',$categoryString); 
     } else { 
      $temp[$catParts[0]] = []; 
     } 

    } 
    foreach($temp as $elemName => $elemVal){ 
     $result[$elemName] = buildTree($elemVal); 
    } 
    return $result; 
} 

var_dump(buildTree($cat)); 
+0

Вот что я искал. Спасибо @ Томас Зима. –

+0

Это способ узнать, сколько категорий было дубликатов? например, «Аксессуары/Ювелирные изделия/Мужчины» - в 2 раза, а массив результатов - как массив («accessories» => array («jewelery» => array («men» => 2))) –

2

Самый простой способ состоит в использовании ссылки, например:

$out = []; 
foreach ($cat as $str) { 
    $lookup =& $out; 
    foreach (explode("/", $str) as $part) { 
     $lookup =& $lookup[$part]; 
     if (!isset($lookup)) { 
      $lookup = []; 
     } 
    } 
} 

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

Обратите внимание, что каждый добавленный новый элемент выглядит как member-name => [], так что фактически даже окончательные листья представляют собой массивы: это может показаться немного странным, но это прекрасный способ иметь уменьшенный код (каждый член всегда готов принять детей) ,

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

function nest_print($src, $level = 0) { 
    $prefix = '<br />' . str_repeat('- ', ++$level); 
    foreach ($src as $key => $val) { 
     echo $prefix . $key; 
     if ($val) { 
      nest_print($val, $level); 
     } 
    } 
} 

nest_print($out); 

EDIT

Вот альтернативное решение, в том числе подсчета из окончательных листов, по просьбе ОП в его комментарии:

$out = []; 
foreach ($cat as $str) { 
    $lookup =& $out; 
    $parts = explode("/", $str); 
    foreach ($parts as $part) { 
     $lookup =& $lookup[$part]; 
     if (!isset($lookup)) { 
      $lookup = []; 
     } 
     // when $part is a final leaf, count its occurrences 
     if ($part == end($parts)) { 
      $lookup = is_array($lookup) ? 1 : ++$lookup; 
     } 
    } 
} 

(возможно, может быть улучшено в более элегантный способ, хотя)

А вот как изменить печать результата фрагмент соответственно:

function nest_print($src, $level = 0) { 
    $prefix = '<br />' . str_repeat('- ', ++$level); 
    foreach ($src as $key => $val) { 
     echo $prefix . $key; 
     if (is_array($val)) { 
      nest_print($val, $level); 
     } else { 
      echo ': ' . $val; 
     } 
    } 
} 

nest_print($out); 
+0

это способ узнать, сколько категорий было дублированием? например, «Аксессуары/Ювелирные изделия/Мужчины» - в 2 раза, а массив результатов - как массив («accessories» => array («jewelery» => array («men» => 2))) –

+0

wow, спасибо ! ты жжешь! он работает хорошо, но у меня есть эта ошибка. Предупреждение. Нельзя использовать скалярное значение в виде массива в этой строке. $ lookup = & $ lookup [$ part]; " –

+0

@MadalinAlexandru Weird ... Я только что проверил с тем же самым фрагментом, что и выше, и я не получаю никаких ошибок. Получаете ли вы его один или несколько шагов? В любом случае, вы можете добавить 'echo '
'. $ str. '->'. $ part; 'непосредственно перед' $ lookup = & $ lookup [$ part]; 'строка и сообщить, что вы получаете? – cFreed