2010-10-21 76 views
1

我有类别的数组:排序分类用PHP阵列

categories = computers, entertainment, products, graphics cards 

阵列被以错误的顺序有时返回,但每一类具有存在相同的阵列中的父节点。

categories = 
products[parent=0], 
entertainment[parent=products], 
computers[parent=entertainment], 
graphics cards[parent=computers] 

如果以任何顺序返回,我将如何使用php对此数组进行排序?

无序例子:

categories = 
computers[parent=entertainment], 
entertainment[parent=products], 
products[parent=0], 
graphics cards[parent=computers]  

必须出示:

categories = products, entertainment, computers, graphics cards 
+0

你说哟你想做一个拓扑排序? – 2010-10-21 19:30:14

+1

这是某种*如何从代表分层数据的数据库记录构建分层数组?*问题? – Gumbo 2010-10-21 19:30:19

+0

它是,但类别数组不是以正确的顺序返回。 – InnateDev 2010-10-21 19:55:26

回答

0

你说的是一个简单的排序是这样的:

<?php 


$categories = array('computers[parent=entertainment]', 
'entertainment[parent=products]', 
'products[parent=0]', 
'graphics cards[parent=computers]'); 
sort($categories); 
echo '<pre>'; 
print_r($categories); 
echo '</pre>'; 

?> 
0

看着你的榜样,我假设正如Sam Dufel所说,你需要一种拓扑排序。

$categories = array(
    "computers" => array("parent" => "entertainment"), 
    "entertainment" => array("parent" => "products"), 
    "products" => array("parent" => null), 
    "graphics cards" => array("parent" => "computers") 
); 

// Set distances 
foreach ($categories as $cat => &$e) { 
    $e["dist"] = nodeDistance($cat, $categories); 
} 

// Before 
echo implode(", ", array_keys($categories)) . "\n"; 
// Sort 
uasort($categories, "nodeDistanceSorter"); 
// After 
echo implode(", ", array_keys($categories)) . "\n"; 

function nodeDistance($node, $categories) { 
    // Check cache 
    if (array_key_exists("dist", $categories[$node])) 
     return $categories[$node]["dist"]; 
    // Check root 
    if (is_null($categories[$node]["parent"])) 
     return 0; 
    // Traverse 
    return nodeDistance($categories[$node]["parent"], $categories) + 1; 
} 

function nodeDistanceSorter($a, $b) { 
    $aDist = $a["dist"]; 
    $bDist = $b["dist"]; 
    if ($aDist == $bDist) 
     return 0; 
    return $aDist - $bDist; 
} 
0
categories = 
products[parent=0], 
entertainment[parent=products], 
computers[parent=entertainment], 
graphics cards[parent=computers] 

我认为该阵列是这样的:

$categories = array 
(
    'products'=>array('parent'=>0),//poor little orphan 
    'entertainment'=>array('parent'=>'products'), 
    'computers'=>array('parent'=>'entertainment'), 
    'graphics cards'=>array('parent'=>'computers'), 
) 

这里是一个解决方案,我现在混合起来:

溶液1

$categories = array 
(
'computers'=>array('parent'=>'entertainment'), 
'entertainment'=>array('parent'=>'products'), 
'products'=>array('parent'=>0), 
'graphics cards'=>array('parent'=>'computers') 
); 

function addparentfirst(&$original,$array,$name,$data){ 
    if(isset($data['parent']) && isset($original[$data['parent']])){ 
     $array = addparentfirst($original,$array,$data['parent'],$original[$data['parent']]); 
    } 
    $array[$name] = $data; 
    unset($original[$name]); 
    return $array; 
} 
foreach($categories as $key=>$value){//goes over each category only once, contrary to what it looks like 
    $sortedcategories = addparentfirst($categories,$sortedcategories,$key,$value); 
} 
$categories = $sortedcategories;//NOW IT'S SORTED 

print_r($categories); 

解决方案2

//It's interesting that it doesn't loop infinitely 
//I like this solution the most 

function addparentfirst(&$array,$key){ 
    if(isset($array[$key]['parent']) && !empty($array[$key]['parent'])){ 
     addparentfirst($array,$array[$key]['parent']); 
    } 
    $data = $array[$key]; 
    unset($array[$key]); 
    $array[$key] = $data; 
    return $array; 
} 


foreach($categories as $key=>$value){ 
    addparentfirst($categories,$key); 
} 
print_r($categories); 

解决方案3

function sortArrayByArray($array,$orderArray) { 
    $ordered = array(); 
    foreach($orderArray as $key) { 
     if(isset($array[$key])) { 
       $ordered[$key] = $array[$key]; 
       unset($array[$key]); 
     } 
    } 
    return $ordered + $array; 
} 



//Usage: 
$categories = sortArrayByArray($categories,array('products','entertainment','computers','graphics cards')); 
print_r($categories); 

as seen here

解决方案4

function get_childless_category_name($array){ 
    foreach($array as $key=>$value){ 
     if(isset($value['parent']) && !empty($value['parent'])){ 
      unset($array[$value['parent']]); 
     } 
    } 
    $names = array_keys($array);//names of all the child free categories 
    return array_pop($names);//get the last one (there should only be one) 
} 
function parent_comes_first(&$array,$key){ 
    if(isset($array[$key]['parent']) && !empty($array[$key]['parent'])){ 
     $array = parent_comes_first($array,$array[$key]['parent']); 
    } 
    $data = $array[$key]; 
    unset($array[$key]); 
    $array[$key] = $data; 
    return $array; 
} 


//Usage: 
$childless = get_childless_category_name($categories); 
parent_comes_first($categories,$childless); 

print_r($categories);