2013-03-13 20 views
8

http://jsfiddle.net/eYgGK/hierarchiczne json z płaskim z macierzystej ID

Wygrałem ten skrypt z innego wątku:

function convertToHierarchy() { 
var arry = [{ "Id": "1", "Name": "abc", "Parent": "", "attr": "abc" }, 
       { "Id": "2", "Name": "abc", "Parent": "1", "attr": "abc" }, 
       { "Id": "3", "Name": "abc", "Parent": "2", "attr": "abc" }, 
       { "Id": "4", "Name": "abc", "Parent": "2", "attr": "abc" }]; 
     var nodeObjects = createStructure(arry); 
     for (var i = nodeObjects.length - 1; i >= 0; i--) { 
      var currentNode = nodeObjects[i]; 
      if (currentNode.value.Parent === "") { 
       continue; 
      } 
      var parent = getParent(currentNode, nodeObjects); 

      if (parent === null) { 
       continue; 
      } 

      parent.children.push(currentNode); 
      nodeObjects.splice(i, 1); 
     } 
     console.dir(nodeObjects); 
     return nodeObjects; 
    } 
    function createStructure(nodes) { 
     var objects = []; 

     for (var i = 0; i < nodes.length; i++) { 
      objects.push({ value: nodes[i], children: [] }); 
     } 

     return objects; 

    } 
    function getParent(child, nodes) { 
     var parent = null; 

     for (var i = 0; i < nodes.length; i++) { 
      if (nodes[i].value.Id === child.value.Parent) { 
       return nodes[i]; 
      } 
     } 

     return parent; 
    } 

Ten skrypt produkuje:

[{ 
    "value": { 
     "Id": "1", 
     "Name": "abc", 
     "Parent": "", 
     "attr": "abc" 
    }, 
    "children": [{ 
     "value": { 
      "Id": "2", 
      "Name": "abc", 
      "Parent": "1", 
      "attr": "abc" 
     }, 
     "children": [{ 
      "value": { 
       "Id": "4", 
       "Name": "abc", 
       "Parent": "2", 
       "attr": "abc" 
      }, 
      "children": [] 
     }, { 
      "value": { 
       "Id": "3", 
       "Name": "abc", 
       "Parent": "2", 
       "attr": "abc" 
      }, 
      "children": [] 
     }] 
    }] 
}] 

Co szukam jest:

[{ 
    "Id": "1", 
    "Name": "abc", 
    "Parent": "", 
    "attr": "abc", 
    "children": [{ 

     "Id": "2", 
     "Name": "abc", 
     "Parent": "1", 
     "attr": "abc", 
     "children": [{ 

      "Id": "4", 
      "Name": "abc", 
      "Parent": "2", 
      "attr": "abc" 
     }, { 

      "Id": "3", 
      "Name": "abc", 
      "Parent": "2", 
      "attr": "abc" 

     }] 
    }] 
}] 

Muszę pozbyć się przede wszystkim opakowania "wartościowego", a po drugie pustego węzła podrzędnego. Wiem, że mogę napisać skrypt czyszczący, ale to byłoby mniej niż najlepsza praktyka. Byłoby świetnie, gdyby ktoś wiedział, jak to naprawić, lub zaproponuj inny skrypt!

Dzięki

Odpowiedz

17

Spróbuj coś

var arry = [{ "Id": "1", "Name": "abc", "Parent": "", "attr": "abc" }, 
       { "Id": "2", "Name": "abc", "Parent": "1", "attr": "abc" }, 
       { "Id": "3", "Name": "abc", "Parent": "2", "attr": "abc" }, 
       { "Id": "4", "Name": "abc", "Parent": "2", "attr": "abc" }]; 

function convert(array){ 
    var map = {}; 
    for(var i = 0; i < array.length; i++){ 
     var obj = array[i]; 
     obj.items= []; 

     map[obj.Id] = obj; 

     var parent = obj.Parent || '-'; 
     if(!map[parent]){ 
      map[parent] = { 
       items: [] 
      }; 
     } 
     map[parent].items.push(obj); 
    } 

    return map['-'].items; 

} 

var r = convert(arry) 

Demo: Fiddle

Wynik

[{ 
    "Id" : "1", 
    "Name" : "abc", 
    "Parent" : "", 
    "attr" : "abc", 
    "children" : [{ 
       "Id" : "2", 
       "Name" : "abc", 
       "Parent" : "1", 
       "attr" : "abc", 
       "children" : [{ 
          "Id" : "3", 
          "Name" : "abc", 
          "Parent" : "2", 
          "attr" : "abc", 
          "children" : [] 
         }, { 
          "Id" : "4", 
          "Name" : "abc", 
          "Parent" : "2", 
          "attr" : "abc", 
          "children" : [] 
         }] 
      }] 
}] 
+1

Świetna robota Arun !! Stukrotne dzięki! – LastTribunal

+0

Arun, czy wiesz, jak zmienić nazwę atrybutu "children" na "items"? – LastTribunal

+0

@ 655321 zobacz aktualizację –

2
function convert(rows) { 
    function exists(rows, Parent) { 
      for (var i = 0; i < rows.length; i++) { 
        if (rows[i].Id == Parent) return true; 
      } 
      return false; 
    } 
    var nodes = []; 
    // get the top level nodes 
    for (var i = 0; i < rows.length; i++) { 
      var row = rows[i]; 
      if (!exists(rows, row.Parent)) { 
        nodes.push({ 
          id: row.Id, 
          name: row.Name, 
          attr: row.attr 
        }); 
      } 
    } 
    var toDo = []; 
    for (var i = 0; i < nodes.length; i++) { 
      toDo.push(nodes[i]); 
    } 
    while (toDo.length) { 
      var node = toDo.shift(); 
      // the parent node 
      // get the children nodes 
      for (var i = 0; i < rows.length; i++) { 
        var row = rows[i]; 
        if (row.Parent == node.Id) { 
          var child = { 
            Id: row.Id, 
            Name: row.Name, 
            attr: row.attr 
          }; 
          if (node.options) { 
            node.options.push(child); 
          } else { 
            node.options = [child]; 
          } 
          toDo.push(child); 
        } 
      } 
    } 
    return nodes;} 
+0

Myślę, że ta odpowiedź jest lepsza. Nawet jeśli węzły najwyższego poziomu nie są pierwszym elementem tablicy, działa to dobrze. –

3
odpowiedź

@Arun P Johny jest dobry, ale ma problem , gdy tablica nie jest posortowana, opróżni pod-drzewa. Zaktualizowałem to w ten sposób.

var arry = [ 
       { "Id": "5", "Name": "abc", "Parent": "3", "attr": "abc" }, 
       { "Id": "2", "Name": "abc", "Parent": "1", "attr": "abc" }, 
       { "Id": "4", "Name": "abc", "Parent": "2", "attr": "abc" }, 
       { "Id": "3", "Name": "abc", "Parent": "2", "attr": "abc" }, 
       { "Id": "1", "Name": "abc", "Parent": "", "attr": "abc" } 
       ]; 

function convert(array){ 
    var map = {} 
    for(var i = 0; i < array.length; i++){ 
     var obj = array[i] 
     if(!(obj.Id in map)){ 
      map[obj.Id] = obj 
      map[obj.Id].children = [] 
     } 

     if(typeof map[obj.Id].Name == 'undefined'){ 
      map[obj.Id].Id = obj.Id 
      map[obj.Id].Name = obj.Name 
      map[obj.Id].attr = obj.attr 
      map[obj.Id].Parent= obj.Parent 
     } 

     var parent = obj.Parent || '-'; 
     if(!(parent in map)){ 
      map[parent] = {} 
      map[parent].children = [] 
     } 

     map[parent].children.push(map[obj.Id]) 
    } 
    return map['-'] 
} 
console.log(JSON.stringify(convert(arry))) 

Rezultatem jest jak ten:

{ 
    "children": [ 
    { 
     "children": [ 
     { 
      "Id": "2", 
      "Name": "abc", 
      "Parent": "1", 
      "attr": "abc", 
      "children": [ 
      { 
       "Id": "4", 
       "Name": "abc", 
       "Parent": "2", 
       "attr": "abc", 
       "children": [] 
      }, 
      { 
       "children": [ 
       { 
        "Id": "5", 
        "Name": "abc", 
        "Parent": "3", 
        "attr": "abc", 
        "children": [] 
       } 
       ], 
       "Id": "3", 
       "Name": "abc", 
       "attr": "abc", 
       "Parent": "2" 
      } 
      ] 
     } 
     ], 
     "Id": "1", 
     "Name": "abc", 
     "attr": "abc", 
     "Parent": "" 
    } 
    ] 
} 
+0

Świetna odpowiedź! ... –

0

// spróbuj tak ...................

function prepareFlatArrayListToTreeViewList(arry) { 
    var treeviewList= angular.copy(flatListToTreeViewData(arry)); 
    return treeviewList; 
} 

// return json format data

function flatListToTreeViewData(dataList) { 
    var tree = [], 
     mappedArr = {}, 
     arrElem, 
     mappedElem; 

    // First map the nodes of the array to an object -> create a hash table. 
    for (var i = 0, len = dataList.length; i < len; i++) { 
     arrElem = dataList[i]; 
     mappedArr[arrElem.id] = arrElem; 
     mappedArr[arrElem.id]['children'] = []; 
    } 

    for (var id in mappedArr) { 
     if (mappedArr.hasOwnProperty(id)) { 
      mappedElem = mappedArr[id]; 

      // If the element is not at the root level, add it to its parent array of children. 
      if (mappedElem.parentID) { 
       mappedArr[mappedElem['parentID']]['children'].push(mappedElem); 
      } 
       // If the element is at the root level, add it to first level elements array. 
      else { 
       tree.push(mappedElem); 
      } 
     } 
    } 
    return tree; 
}