2016-04-13 13 views
4

Ich habe ein Array von Objekten mit ParentId und Sortierwerte, die ich in ein Array mit verschachtelten "Kinder" und sortiert werden möchte.JavaScript-Format Array von Objekten in verschachtelte Kinder

Zum Beispiel ist hier die Daten:

[{ 
    id: 1, 
    sort: 2, 
    parentId: null, 
    name: 'A' 
}, { 
    id: 2, 
    sort: 1, 
    parentId: 1, 
    name: 'A.1' 
}, { 
    id: 3 
    sort: 2, 
    parentId: 1, 
    name: 'A.2' 
}, { 
    id: 4, 
    sort: 1, 
    parentId: null, 
    name: 'B' 
}] 

Die Art und Weise Ich mag würde dies wäre zu transformieren, wie:

[{ 
    id: 4, 
    sort: 1, 
    parentId: null, 
    name: 'B', 
    children: [] 
}, { 
    id: 1, 
    sort: 2, 
    parentId: null, 
    name: 'A', 
    children: [{ 
     id: 2, 
     sort: 1, 
     parentId: 1, 
     name: 'A.1' 
    }, { 
     id: 3 
     sort: 2, 
     parentId: 1, 
     name: 'A.2' 
    }] 
}] 

Diese sortiert ist (id 4 an der Spitze zu sein, seit sortierung ist 1) und die kinder sind verschachtelt und auch entsprechend sortiert.

Irgendwelche Vorschläge für eine gute Möglichkeit, dies zu tun? Ich kann rekursiv durchlaufen, um Kinder anzuwenden, aber nicht sicher, wie ich das sortieren kann.

+0

Sind die 'Sie Angaben zu einem Zeichen nur? Ist der erste Teil des 'Namens' nur alphabetisch wie in' A-Z' oder gibt es Zahlen und Sonderzeichen? – stackErr

+0

@stackErr Ich denke, Namen sind hier überhaupt nicht wichtig, Sie brauchen sie nicht, um die Frage zu beantworten. Er fügte diese für uns hinzu, um leichter zu sehen, wohin alles gehen sollte. – blex

+0

@stackErr Ja, die Namen sind nur aus Gründen der Einfachheit des Beispiels. Die gesamte Logik würde auf id, parentId und sort basieren. – dzm

Antwort

3

Dies ist ein Vorschlag, der erste und der Filter danach sortiert.

Die Sortierung übernimmt die Eigenschaften parentId und sort. Dies ist für den nächsten Schritt notwendig, da das "Filtern" ein sortiertes Array benötigt.

Später wird das Array mit Array#filter() gefiltert, hier wird thisArgs für Referenzierungsknoten für eine mögliche Einfügung von Kindern verwendet.

Bearbeiten: Update für unsortierte (id/parentId) Daten.

var array = [{ id: 1, sort: 2, parentId: null, name: 'A' }, { id: 2, sort: 1, parentId: 1, name: 'A.1' }, { id: 3, sort: 2, parentId: 1, name: 'A.2' }, { id: 4, sort: 1, parentId: null, name: 'B' }], 
 
    nested; 
 

 
array.sort(function (a, b) { 
 
    return (a.parentId || -1) - (b.parentId || -1) || a.sort - b.sort; 
 
}); 
 

 
nested = array.filter(function (a) { 
 
    a.children = this[a.id] && this[a.id].children; 
 
    this[a.id] = a; 
 
    if (a.parentId === null) { 
 
     return true; 
 
    } 
 
    this[a.parentId] = this[a.parentId] || {}; 
 
    this[a.parentId].children = this[a.parentId].children || []; 
 
    this[a.parentId].children.push(a); 
 
}, Object.create(null)); 
 

 
document.write('<pre>' + JSON.stringify(nested, 0, 4) + '</pre>');

+1

This scheint gut zu funktionieren, vielen Dank. – dzm

+0

Dies funktioniert nicht immer, weil es die 'parentId' verwendet, um die Daten zu sortieren, was irrelevant ist. Versuchen Sie es mit: '[{id: 1, parentId: null, sortieren: 1}, {id: 2, parentId: 3, sort: 1}, {id: 3, parentId: 2, sort: 1}]' und Sie werden sich mit einer Ausnahme finden. Ansonsten ist der 'thisArg' Trick auf' filter' wirklich nett. – VonD

+0

Ihre Daten sind nicht gültig. es hat einen Zirkelbezug. 2 -> 3, 3 -> 2 –

0
  1. würde ich eine neue Datenstruktur, erstellen, um wie folgt aussehen:

    {1: { id: 1, Art: 2, parentId: null, Name: 'A' }, 2: { ID: 4, sort: 1, parentId: null, Name: 'B' } }

Dinge zu bemerken: Die neue Struktur ist ein Objekt, kein Array, das nur die obersten Elemente darin (die mit parentIdnull)

    enthält
  1. dann Führen Sie den Original-Array ein for über und new_obj[ orig_arr_curr_elem[parentId] ].children.push(orig_arr_curr_elem)

  2. Dann ein neues Array mit der elems erstellen zuweisen aus new_objsort() den (oder der children Eigenschaft), aber Sie wollen

Code, der die Schritte 1 und 2 (unter Verwendung von diesen ausführen Knoten) implementiert:

var util = require('util'); 
var old_arr = [{ 
    id: 1, 
    sort: 2, 
    parentId: null, 
    name: 'A' 
}, { 
    id: 2, 
    sort: 1, 
    parentId: 1, 
    name: 'A.1' 
}, { 
    id: 3, 
    sort: 2, 
    parentId: 1, 
    name: 'A.2' 
}, { 
    id: 4, 
    sort: 1, 
    parentId: null, 
    name: 'B' 
}]; 

var new_obj = {}; 
for (var i = 0; i < old_arr.length; i++){ 
    if (old_arr[i].parentId == null) 
     new_obj[ old_arr[i].id ] = old_arr[i]; 
} 

for (var i = 0; i < old_arr.length; i++){ 
    if (old_arr[i].parentId == null) continue; 
    new_obj[ old_arr[i].parentId ].children = new_obj[ old_arr[i].parentId ].children || []; 
    new_obj[ old_arr[i].parentId ].children.push(old_arr[i]); 
} 

console.log(util.inspect(new_obj, {showHidden: false, depth: null})); 
2

gab es mir einen Versuch und kam zurück, und es gibt bereits andere Antworten, aber ich bin es trotzdem zu veröffentlichen.

Diese Methode modifiziert das ursprüngliche Array:

var items = [{id: 1,sort: 2,parentId: null,name: 'A'}, {id: 2,sort: 1,parentId: 1,name: 'A.1'}, {id: 3,sort: 2,parentId: 1,name: 'A.2'}, {id: 4,sort: 1,parentId: null,name: 'B'}]; 
 

 

 
function generate_tree(arr){ 
 
    var references = {}; 
 
    arr.sort(function(a,b){ 
 
    // Save references to each item by id while sorting 
 
    references[a.id] = a; references[b.id] = b; 
 
    // Add a children property 
 
    a.children = []; b.children = []; 
 
    if(a.sort > b.sort) return 1; 
 
    if(a.sort < b.sort) return -1; 
 
    return 0; 
 
    }); 
 

 
    for(var i=0; i<arr.length; i++){ 
 
    var item = arr[i]; 
 
    if(item.parentId !== null && references.hasOwnProperty(item.parentId)){ 
 
     references[item.parentId].children.push(arr.splice(i,1)[0]); 
 
     i--; // Because the current index now contains the next item 
 
    } 
 
    } 
 
    return arr; 
 
} 
 

 
document.body.innerHTML = "<pre>" + JSON.stringify(generate_tree(items), null, 4) + "</pre>";

Verwandte Themen