2017-06-01 43 views
0

注意:下面的解決方案!如何創建對象的平面數組,樹陣,然後在每個級別編號每個樹節點的水平和排序的節點?

問題: 我所需的代碼把有ID和父值對象的扁平陣列成一棵樹。由於平面陣列是動態生成的,所以深度級別數量未知。另外,一旦項目在樹中,我需要爲節點分配一個級別屬性值,具體取決於它們所處的樹級別(根節點=級別0,根節點的子節點=級別1,兒童的孩子= 2級等)。

最後,在每個樹級別的節點應該通過阿爾法其ID進行排序。所以根ID應該進行排序,然後根部孩子,那麼孩子的孩子,等等等等

我找到了一些解決方案,滿足至少兩個我的要求,但沒有能夠滿足所有三個。

解決方案:jsfiddle

var x = [ 
{id: 10, parent: 0, children: []}, 
{id: 20, parent: 10, children: []}, 
{id: 30, parent: 10, children: []}, 
{id: 40, parent: 30, children: []}, 
{id: 50, parent: 30, children: []}, 
{id: 60, parent: 30, children: []}, 
{id: 70, parent: 20, children: []}, 
{id: 80, parent: 20, children: []}, 
{id: 90, parent: 40, children: []}, 
{id: 100, parent: 40, children: []}, 
{id: 95, parent: 40, children: []}, 
{id: 110, parent: 50, children: []}, 
{id: 120, parent: 60, children: []}, 
{id: 130, parent: 0, children: []}, 
{id: 140, parent: 130, children: []}, 
{id: 150, parent: 140, children: []}, 
{id: 160, parent: 140, children: []}, 
{id: 170, parent: 140, children: []}, 
{id: 180, parent: 160, children: []}, 
{id: 190, parent: 160, children: []}, 
{id: 200, parent: 190, children: []} 
]; 

進入這個:

<!DOCTYPE html> 
<html> 
<head> 
    <title></title> 
</head> 
<body> 
    <ul> 
     <li>10 
      <ul> 
       <li>20 
        <ul> 
         <li>70</li> 
         <li>80</li> 
        </ul> 
       </li> 
       <li>30 
        <ul> 
         <li>40 
          <ul> 
           <li>90</li> 
           <li>95</li> 
           <li>100</li> 
          </ul> 
         </li> 
         <li>50 
          <ul> 
           <li>110</li> 
          </ul> 
         </li> 
         <li>60 
          <ul> 
           <li>120</li> 
          </ul> 
         </li> 
        </ul> 
       </li> 
      </ul> 
     </li> 
     <li>130 
      <ul> 
       <li>140 
        <ul> 
         <li>150</li> 
         <li>160 
          <ul> 
           <li>180</li> 
           <li>190 
            <ul> 
             <li>200</li> 
            </ul> 
           </li> 
          </ul> 
         </li> 
         <li>170</li> 
        </ul> 
       </li> 
      </ul> 
     </li> 
    </ul> 
</body> 
</html> 

回答

-1

在我的小提琴曾經消失的情況下,這是我的完整的解決方案:

<html> 

<script> 
window.onload = function() { 

// STEP 1: Get a flat array of objects. 

/* A flat (1 dimensional) array, which can later be turned into a tree, since each array item has an id and parent property. */ 
var x = [ 
{id: 10, parent: 0, children: []}, // 2 immediate children, root node 
{id: 20, parent: 10, children: []}, // 2 immediate children 
{id: 30, parent: 10, children: []}, // 3 immediate children 
{id: 40, parent: 30, children: []}, // 3 immediate children 
{id: 50, parent: 30, children: []}, // 1 immediate children 
{id: 60, parent: 30, children: []}, // 1 immediate children 
{id: 70, parent: 20, children: []}, // 0 immediate children 
{id: 80, parent: 20, children: []}, // 0 immediate children 
{id: 90, parent: 40, children: []}, // 0 immediate children 
{id: 100, parent: 40, children: []}, // 0 immediate children 
{id: 95, parent: 40, children: []}, // 0 immediate children 
{id: 110, parent: 50, children: []}, // 0 immediate children 
{id: 120, parent: 60, children: []}, // 0 immediate children 
{id: 130, parent: 0, children: []}, // 1 immediate children, root node 
{id: 140, parent: 130, children: []}, // 3 immediate children 
{id: 150, parent: 140, children: []}, // 0 immediate children 
{id: 160, parent: 140, children: []}, // 2 immediate children 
{id: 170, parent: 140, children: []}, // 0 immediate children 
{id: 180, parent: 160, children: []}, // 0 immediate children 
{id: 190, parent: 160, children: []}, // 1 immediate children 
{id: 200, parent: 190, children: []} // 0 immediate children; 5 levels deep (level = 4, since start level is 0) 
]; 


// STEP 2: Turn the flat array into a tree (hierarchical) array. 

function tierData (arr) { 
/* 
    Params: 
     @arr = flat array. Each array item is an object containing id, parent, and children properties. 

    Description: 
     Takes a flat array and turns into into a tree (hierarchical) array. 
*/ 
    for (var i = 0; i < arr.length; i++) { 
     arr.forEach(function (n) { 
      if (n.parent === arr[i].id) { 
       arr[i].children.push(n); 
      }   
     }); 
    } 
    return arr.filter(function (n) { return n.parent === 0 }); // Only return root nodes and their children, children's children, etc. 
} 

var td = tierData(x); 
//console.log(td); 


// STEP 3: Assign a "level" property to each tree level. Numeric sort tree items for each level in the tree. 

function treeSortAndLevel (treeArr,flatArr,flatIndex) { 
/* 
    Params: 
     @treeArr = A tree (hierarchical) array, created from a flat array using the tierData fn. 
     @flatArr = A flat array on which @treeArr is based. 
     @flatIndex = DON'T PASS AN ARG. This is assigned a value by subsequent recursive fn calls. 

    Description: 
     Returns a tree which is numeric sorted at each level and each tree node is assigned a level property value, starting with root node(s) level = 0. 
*/ 
    // If not provided (ie the fn's first call), create an indexer for the flat array. 
    if (flatIndex === undefined) { 
     var flatIndex = {}; 
     for (var i = 0; i < flatArr.length; i++) { 
      flatIndex[flatArr[i].id] = flatArr[i];  
     } 
    } 

    for (var i = 0; i < treeArr.length; i++) { 
     // Numeric sort the current treeArr tier (ie array) by id. 
     treeArr.sort(function (a, b) { return a.id - b.id; }); 
     // Determine and set the treeArr item's level. 
     var parentId = treeArr[i].parent; 
     var level = 0; 
     while (parentId !== 0) { 
      level++; 
      var ancestor; 
      ancestor = flatIndex[parentId]; 
      parentId = ancestor.parent; 
     } 
     treeArr[i].level = level; 
     treeSortAndLevel(treeArr[i].children,flatArr,flatIndex); 
    } 
    return treeArr; 
} 

var sortedAndLeveldTree = treeSortAndLevel(td,x); 

console.log(sortedAndLeveldTree); 


// STEP 4: Append a multi-tiered unordered list to the DOM for the sorted and level numbered tree. 

function printTree (treeArr) { 
/* 
    Params: 
     @treeArr = A tree (hierarchical) array, created from a flat array using the tierData fn. 

    Description: 
     Prints a tree to the console. 
*/ 
    for (var i = 0; i < treeArr.length; i++) { 
     var indent = ''; 
     var level = treeArr[i].level; 
     while (level > 0) { 
      indent += ' -- '; 
      level--; 
     } 
     console.log(indent + treeArr[i].id);  
     printTree(treeArr[i].children); 
    } 
} 

function createTreeDOM (treeArr, ul) { 
/* 
    Params: 
     @treeArr = A tree (hierarchical) array, created from a flat array using the tierData fn. 
     @ul = DON'T PASS AN ARG. This is assigned a value by subsequent recursive fn calls. 

    Description: 
     Returns an unordered list tree (DOM element). 
*/ 
    if (ul === undefined) { 
     ul = document.createElement('ul'); 
    } 
    for (var i = 0; i < treeArr.length; i++) { 
     var li = document.createElement('li'); 
     var tx = document.createTextNode(treeArr[i].id); 
     li.appendChild(tx); 
     if (treeArr[i].children.length > 0) { 
      var subUL = document.createElement('ul'); 
      li.appendChild(subUL); 
      createTreeDOM(treeArr[i].children, subUL); 
     } 
     ul.appendChild(li); 
    } 
    return ul; 
} 

// Alternatively, print the sorted and level numbered tree to the console in a tree-like style using the printTree fn: 
//printTree(sortedAndLeveldTree); 

var p = document.createElement('p'); 
p.innerHTML = 'The below tree was dynamically created from a flat array of objects using JS. Tree items (the objects, not the DOM elements) are assigned a level property, starting with 0 for root items. Tree items are sorted by their id at each tier (tree level).'; 
document.body.appendChild(p); 

var treeDOM = createTreeDOM(sortedAndLeveldTree); 
document.body.appendChild(treeDOM); 

} 
</script> 

</html> 
0

您可以先構建樹對象,然後渲染所需的html結構。

爲獲得排序結果,我建議先使用兩級方法排序數據,首先排序parent,然後排序id

要返回想要的級別,可以將level變量添加到getTree,如果未設置,則初始化爲零。

增量爲每一個更深層次的此值。

function getTree(array, level) { 
 
    var ul = document.createElement('ul'); 
 
    level = level || 0; 
 
    array.forEach(function (a) { 
 
     var li = document.createElement('li'); 
 
     li.appendChild(document.createTextNode(a.id + ' level: ' + level)); 
 
     Array.isArray(a.children) && li.appendChild(getTree(a.children, level + 1)); 
 
     ul.appendChild(li); 
 
    }); 
 
    return ul; 
 
} 
 

 
var data = [{ id: 10, parent: 0 }, { id: 20, parent: 10 }, { id: 30, parent: 10 }, { id: 40, parent: 30 }, { id: 50, parent: 30 }, { id: 60, parent: 30 }, { id: 70, parent: 20 }, { id: 80, parent: 20 }, { id: 90, parent: 40 }, { id: 100, parent: 40 }, { id: 95, parent: 40 }, { id: 110, parent: 50 }, { id: 120, parent: 60 }, { id: 130, parent: 0 }, { id: 140, parent: 130 }, { id: 150, parent: 140 }, { id: 160, parent: 140 }, { id: 170, parent: 140 }, { id: 180, parent: 160 }, { id: 190, parent: 160 }, { id: 200, parent: 190 }], 
 
    tree = function (data, root) { 
 
     var r = [], 
 
      o = {}; 
 

 
     data.forEach(function (a) { 
 
      a.children = o[a.id] && o[a.id].children; 
 
      o[a.id] = a; 
 
      if (a.parent === root) { 
 
       r.push(a); 
 
      } else { 
 
       o[a.parent] = o[a.parent] || {}; 
 
       o[a.parent].children = o[a.parent].children || []; 
 
       o[a.parent].children.push(a); 
 
      } 
 
     }); 
 
     return r; 
 
    }(data.sort(function (a, b) { return a.parent - b.parent || a.id- b.id; }), 0); 
 

 
document.body.appendChild(getTree(tree)); 
 
console.log(tree);

+0

謝謝,尼娜。我喜歡你的方法,我從來沒有見過以前使用過的「警衛操作員」(我不得不在谷歌中如何使用&&來賦值賦值,並確定是否應該執行一個函數)。不過,您的代碼缺少兩項要求。 1)所有節點必須在每個級別進行alpha排序。在40節點下,它應該是90,95和100個子節點。 2)儘管我沒有在DOM結果中顯示它,但我希望爲每個節點分配一個等級屬性值,該值等於樹中的位置。 –

+1

順便說一句,你的排序是不是阿爾法,但數值,監守阿爾法各種'「100」 <「90」 <「95」,但你需要治療值數(它們是什麼)。 –

+0

排序錯誤的好處。我更新了我的答案和jsfiddle。 –

相關問題