Erstellen Sie ein Baumarray aus einem flachen Array in Javascript

Lesezeit: 6 Minuten

Erstellen Sie ein Baumarray aus einem flachen Array in Javascript
Frank

Ich habe eine komplexe JSON-Datei, die ich mit Javascript bearbeiten muss, um sie hierarchisch zu machen, um später einen Baum zu erstellen. Jeder Eintrag des json hat: id : eine eindeutige id, parentId : die id des übergeordneten Knotens (die 0 ist, wenn der Knoten eine Wurzel des Baums ist) level : die Ebene der Tiefe im Baum

Die json-Daten sind bereits “bestellt”. Ich meine, dass ein Eintrag über sich selbst einen Elternknoten oder Bruderknoten und unter sich selbst einen Kindknoten oder einen Bruderknoten haben wird.

Eingang:

{
    "People": [
        {
            "id": "12",
            "parentId": "0",
            "text": "Man",
            "level": "1",
            "children": null
        },
        {
            "id": "6",
            "parentId": "12",
            "text": "Boy",
            "level": "2",
            "children": null
        },
                {
            "id": "7",
            "parentId": "12",
            "text": "Other",
            "level": "2",
            "children": null
        },
        {
            "id": "9",
            "parentId": "0",
            "text": "Woman",
            "level": "1",
            "children": null
        },
        {
            "id": "11",
            "parentId": "9",
            "text": "Girl",
            "level": "2",
            "children": null
        }
    ],
    "Animals": [
        {
            "id": "5",
            "parentId": "0",
            "text": "Dog",
            "level": "1",
            "children": null
        },
        {
            "id": "8",
            "parentId": "5",
            "text": "Puppy",
            "level": "2",
            "children": null
        },
        {
            "id": "10",
            "parentId": "13",
            "text": "Cat",
            "level": "1",
            "children": null
        },
        {
            "id": "14",
            "parentId": "13",
            "text": "Kitten",
            "level": "2",
            "children": null
        },
    ]
}

Erwartete Ausgabe :

{
    "People": [
        {
            "id": "12",
            "parentId": "0",
            "text": "Man",
            "level": "1",
            "children": [
                {
                    "id": "6",
                    "parentId": "12",
                    "text": "Boy",
                    "level": "2",
                    "children": null
                },
                {
                    "id": "7",
                    "parentId": "12",
                    "text": "Other",
                    "level": "2",
                    "children": null
                }   
            ]
        },
        {
            "id": "9",
            "parentId": "0",
            "text": "Woman",
            "level": "1",
            "children":
            {

                "id": "11",
                "parentId": "9",
                "text": "Girl",
                "level": "2",
                "children": null
            }
        }

    ],    

    "Animals": [
        {
            "id": "5",
            "parentId": "0",
            "text": "Dog",
            "level": "1",
            "children": 
                {
                    "id": "8",
                    "parentId": "5",
                    "text": "Puppy",
                    "level": "2",
                    "children": null
                }
        },
        {
            "id": "10",
            "parentId": "13",
            "text": "Cat",
            "level": "1",
            "children": 
            {
                "id": "14",
                "parentId": "13",
                "text": "Kitten",
                "level": "2",
                "children": null
            }
        }

    ]
}

  • Es gibt mehrere Möglichkeiten, das zu tun, hast du schon etwas ausprobiert?

    – bfavaretto

    2. August 2013 um 13:23 Uhr

  • Ich gehe davon aus, dass a parentId von 0 bedeutet, dass es keine übergeordnete ID gibt und die oberste Ebene sein sollte.

    – Donnie D’Amato

    12. April 2016 um 11:28 Uhr

  • Normalerweise erforderten solche Aufgaben umfangreiche Arbeitswissensobjekte. Gute Frage

    – Gangadhar JANNU

    14. Oktober 2018 um 11:14 Uhr

Erstellen Sie ein Baumarray aus einem flachen Array in Javascript
FurkanO

( BONUS1 : NODES KÖNNEN ODER NICHT BESTELLT WERDEN )

(BONUS2: KEINE DRITTANBIETER-BIBLIOTHEK ERFORDERLICH, PLAIN JS)

( BONUS3 : Benutzer “Elias Rabl” sagt, dass dies die leistungsfähigste Lösung ist, siehe seine Antwort unten )

Hier ist es:

const createDataTree = dataset => {
  const hashTable = Object.create(null);
  dataset.forEach(aData => hashTable[aData.ID] = {...aData, childNodes: []});
  const dataTree = [];
  dataset.forEach(aData => {
    if(aData.parentID) hashTable[aData.parentID].childNodes.push(hashTable[aData.ID])
    else dataTree.push(hashTable[aData.ID])
  });
  return dataTree;
};

Hier ist ein Test, der Ihnen helfen könnte zu verstehen, wie die Lösung funktioniert:

it('creates a correct shape of dataTree', () => {
  const dataSet = [{
    "ID": 1,
    "Phone": "(403) 125-2552",
    "City": "Coevorden",
    "Name": "Grady"
  }, {
    "ID": 2,
    "parentID": 1,
    "Phone": "(979) 486-1932",
    "City": "Chełm",
    "Name": "Scarlet"
  }];

  const expectedDataTree = [{
    "ID": 1,
    "Phone": "(403) 125-2552",
    "City": "Coevorden",
    "Name": "Grady",
    childNodes: [{
      "ID": 2,
      "parentID": 1,
      "Phone": "(979) 486-1932",
      "City": "Chełm",
      "Name": "Scarlet",
      childNodes : []
    }]
  }];

  expect(createDataTree(dataSet)).toEqual(expectedDataTree);
});

  • Wäre es nicht genauer, wenn wir hinzufügen würden childNodes nur bei bedarf? Indem Sie sie von der ersten entfernen forEach und sie in die zweite verschieben?

    – arpl

    15. Oktober 2019 um 15:15 Uhr


  • @FurkanO wirklich schöne Lösung, aber wäre es möglich, mit funktionaler Programmierung (keine Mutationen) in die Nähe dieser Leistung zu kommen?

    – Dac0d3r

    29. April 2020 um 20:54 Uhr

  • Falls jemand mehrere Eltern für ein Kind haben möchte, siehe -> stackoverflow.com/a/65626153/8577819

    – Natrajan

    8. Januar 2021 um 15:05 Uhr


  • Kann ich Kinder eines bestimmten Artikels bekommen?

    – rendom

    20. November 2021 um 5:53 Uhr

  • Für diejenigen, die nach einer generischen Methode suchen, die in TypeScript implementiert ist: gist.github.com/ggondim/35376795cb832103e466fc158db74af4

    – Gustav Gondim

    18. Januar um 0:03

  • Du kannst hinzufügen else { parent['children'] = []; } nach der ersten if-Klausel, um sicherzustellen, dass jeder Knoten ein Attribut hat children (es ist leer, wenn der Knoten ein Blattknoten ist)

    – Christoph

    12. April 2016 um 10:20 Uhr

  • Ihr Code-Snippet hat perfekt funktioniert, danke!! Das einzige ist: tree wird nie als Argument übergeben, wenn die Funktion rekursiv aufgerufen wird, also denke ich, dass die Zeile tree = typeof tree !== 'undefined' ? tree : []; kann ersetzt werden durch let tree = [];

    – Oskar Calderon

    12. Januar 2017 um 13:19 Uhr

  • könnte dies geändert werden, um dies zu ermöglichen null parent_ids statt 0? Bearbeiten: Egal, ich habe es zum Laufen gebracht, indem ich die geändert habe id: 0 zu id: null.

    – dinx90

    23. Januar 2017 um 8:34 Uhr


  • Beachten Sie, dass die obige Antwort zwei Schleifen verwendet und daher verbessert werden könnte. Da ich kein npm-Modul finden konnte, das eine O(n)-Lösung implementiert, habe ich das folgende erstellt (unit getestet, 100% Codeabdeckung, nur 0,5 kb groß und enthält Typisierungen). Vielleicht hilft es jemandem: npmjs.com/package/performant-array-to-tree

    – Philipp Stanislaus

    7. Mai 2017 um 17:42 Uhr

  • Für alle Interessierten lässt sich der Code einfach in Vanilla js umwandeln: jsfiddle.net/LkkwH/853

    – xec

    12. April 2018 um 9:58 Uhr

1646634309 710 Erstellen Sie ein Baumarray aus einem flachen Array in Javascript
shekhardtu

Verwenden Sie diesen ES6-Ansatz. Funktioniert wie Charme

// Data Set
// One top level comment 
const comments = [{
    id: 1,
    parent_id: null
}, {
    id: 2,
    parent_id: 1
}, {
    id: 3,
    parent_id: 1
}, {
    id: 4,
    parent_id: 2
}, {
    id: 5,
    parent_id: 4
}];

const nest = (items, id = null, link = 'parent_id') =>
  items
    .filter(item => itemhttps://stackoverflow.com/questions/18017869/build-tree-array-from-flat-array-in-javascript === id)
    .map(item => ({ ...item, children: nest(items, item.id) }));

console.log(
  nest(comments)
)

  • Die kürzeste und beste Antwort, denke ich

    – bekliev

    29. November 2019 um 7:38 Uhr

  • langsam im Vergleich zu FurkanOs Antwort

    – Geza Turi

    17. Dezember 2019 um 17:44 Uhr

  • funktionieren nicht, wenn das Array mehr als eine null parentId hat

    – Amjad Mehmood

    9. Mai 2021 um 13:32 Uhr

1646634310 96 Erstellen Sie ein Baumarray aus einem flachen Array in Javascript
MAK Ripon

Hatte das gleiche Problem, aber ich konnte nicht sicher sein, dass die Daten waren sortiert oder nicht. Ich konnte keine Bibliothek von Drittanbietern verwenden, also ist dies nur Vanilla Js; Eingabedaten können dem Beispiel von @Stephen entnommen werden;

 var arr = [
        {'id':1 ,'parentid' : 0},
        {'id':4 ,'parentid' : 2},
        {'id':3 ,'parentid' : 1},
        {'id':5 ,'parentid' : 0},
        {'id':6 ,'parentid' : 0},
        {'id':2 ,'parentid' : 1},
        {'id':7 ,'parentid' : 4},
        {'id':8 ,'parentid' : 1}
      ];
    function unflatten(arr) {
      var tree = [],
          mappedArr = {},
          arrElem,
          mappedElem;

      // First map the nodes of the array to an object -> create a hash table.
      for(var i = 0, len = arr.length; i < len; i++) {
        arrElem = arr[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;
    }

var tree = unflatten(arr);
document.body.innerHTML = "<pre>" + (JSON.stringify(tree, null, " "))

JS Geige

Flache Reihe zu Baum

  • Die kürzeste und beste Antwort, denke ich

    – bekliev

    29. November 2019 um 7:38 Uhr

  • langsam im Vergleich zu FurkanOs Antwort

    – Geza Turi

    17. Dezember 2019 um 17:44 Uhr

  • funktionieren nicht, wenn das Array mehr als eine null parentId hat

    – Amjad Mehmood

    9. Mai 2021 um 13:32 Uhr

eine einfachere Funktion list-to-tree-lite

npm install list-to-tree-lite

listToTree(list)

Quelle:

function listToTree(data, options) {
    options = options || {};
    var ID_KEY = options.idKey || 'id';
    var PARENT_KEY = options.parentKey || 'parent';
    var CHILDREN_KEY = options.childrenKey || 'children';

    var tree = [],
        childrenOf = {};
    var item, id, parentId;

    for (var i = 0, length = data.length; i < length; i++) {
        item = data[i];
        id = item[ID_KEY];
        parentId = item[PARENT_KEY] || 0;
        // every item may have children
        childrenOf[id] = childrenOf[id] || [];
        // init its children
        item[CHILDREN_KEY] = childrenOf[id];
        if (parentId != 0) {
            // init its parent's children object
            childrenOf[parentId] = childrenOf[parentId] || [];
            // push it into its parent's children object
            childrenOf[parentId].push(item);
        } else {
            tree.push(item);
        }
    };

    return tree;
}

jsfiddle

963550cookie-checkErstellen Sie ein Baumarray aus einem flachen Array in Javascript

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy