जावास्क्रिप्ट में फ्लैट ऐरे से ट्री ऐरे बनाएं


134

मेरे पास एक जटिल json फ़ाइल है जिसे मुझे बाद में एक पेड़ बनाने के लिए इसे पदानुक्रमित बनाने के लिए जावास्क्रिप्ट के साथ संभालना है। Json की हर प्रविष्टि में है: id: एक अद्वितीय आईडी, parentId: मूल नोड की आईडी (जो 0 है अगर नोड पेड़ की जड़ है) स्तर: पेड़ में गहराई का स्तर

Json डेटा पहले से ही "आदेशित" है। मेरा मतलब है कि एक प्रविष्टि अपने आप में एक माता-पिता के नोड या भाई के नोड के ऊपर होगी, और एक बच्चे के नोड या भाई के नोड के तहत।

इनपुट:

{
    "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
        },
    ]
}

अपेक्षित उत्पादन :

{
    "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
            }
        }

    ]
}

2
ऐसा करने के कई तरीके हैं, क्या आपने अभी तक कुछ भी करने की कोशिश की है?
bfavaretto

मेरा मानना ​​है कि ए parentIdका 0मतलब कोई पेरेंट आईडी नहीं है और यह सबसे ऊपरी परत होनी चाहिए।
डॉनी डी'माटो

आमतौर पर इस तरह के कार्यों के लिए व्यापक कार्यशील ज्ञान वस्तुओं की आवश्यकता होती है। अच्छा प्रश्न
गंगाधर JANNU

जवाबों:


156

यदि आप मानचित्र-लुकअप का उपयोग करते हैं तो एक कुशल समाधान है। यदि माता-पिता हमेशा अपने बच्चों से पहले आते हैं तो आप दो-छोरों को मर्ज कर सकते हैं। यह कई जड़ों का समर्थन करता है। यह झूलती शाखाओं पर एक त्रुटि देता है, लेकिन उन्हें अनदेखा करने के लिए संशोधित किया जा सकता है। इसे तृतीय-पक्ष लाइब्रेरी की आवश्यकता नहीं है। यह, जहां तक ​​मैं बता सकता हूं, सबसे तेज समाधान है।

function list_to_tree(list) {
  var map = {}, node, roots = [], i;
  
  for (i = 0; i < list.length; i += 1) {
    map[list[i].id] = i; // initialize the map
    list[i].children = []; // initialize the children
  }
  
  for (i = 0; i < list.length; i += 1) {
    node = list[i];
    if (node.parentId !== "0") {
      // if you have dangling branches check that map[node.parentId] exists
      list[map[node.parentId]].children.push(node);
    } else {
      roots.push(node);
    }
  }
  return roots;
}

var entries = [{
    "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
  }
];

console.log(list_to_tree(entries));

यदि आप जटिलता सिद्धांत में हैं तो यह समाधान Θ (n लॉग (n)) है। पुनरावर्ती-फ़िल्टर समाधान Θ (n ^ 2) है जो बड़े डेटा सेट के लिए एक समस्या हो सकती है।


28
ध्यान रखें कि इस समाधान के साथ, आपके नोड्स को विशेष रूप से यह सुनिश्चित करने के लिए आदेश दिया जाना चाहिए कि माता-पिता को पहले नक्शे में धकेल दिया जाए, अन्यथा लुकअप प्रक्रिया में त्रुटि होगी ... इसलिए आपको या तो स्तर की संपत्ति पर उन्हें सॉर्ट करने की आवश्यकता है, या आपको आवश्यकता है पहले नक्शे में उन्हें धकेलने के लिए। और लुकअप के लिए एक अलग लूप का उपयोग करें। (मैं तब पसंद करता हूं जब आपके पास एक स्तर की संपत्ति नहीं होती है अलग-अलग छोरों का विकल्प हो सकता है)
सैंडर

मुझे पहली बार यह आश्चर्यजनक लगा कि अतिरिक्त जानकारी होना, जैसे: [१, ५, ६] जैसा एक मार्ग जहां सरणी बाद के पूर्वजों की है, उसमें कुशलता से इस्तेमाल नहीं किया जा सकता है। लेकिन कोड को देखकर यह समझ में आता है क्योंकि मुझे विश्वास है कि यह O (n) है
Ced

1
अच्छे उत्तर के बावजूद, यह जटिल है। मेरे जवाब को सिर्फ दो लाइन कोड के लिए लागू करें: लिंक
ईमान बहरामपुर

कृपया आप बता सकते हैं कि यह समाधान Θ (n log (n)) क्यों है, यह O (n) समय ले रहा है।
अमरेंद्र सिंह

फॉर-लूप के अंदर @amrendersingh एक हैश-लुकिंग है mapजिसमें (सिद्धांत में) O (लॉग एन) है।
हैल्सीओन

72

जैसा कि @Sander, @ Halcyon`s द्वारा वर्णित है पूर्व-क्रमबद्ध सरणी मानता है, निम्नलिखित नहीं है। (हालांकि यह मान लेता है कि आपने अंडरस्कोर लोड किया है। जेएस - हालांकि इसे वेनिला जावास्क्रिप्ट में लिखा जा सकता है):

कोड

// Example usage
var arr = [
    {'id':1 ,'parentid' : 0},
    {'id':2 ,'parentid' : 1},
    {'id':3 ,'parentid' : 1},
    {'id':4 ,'parentid' : 2},
    {'id':5 ,'parentid' : 0},
    {'id':6 ,'parentid' : 0},
    {'id':7 ,'parentid' : 4}
];

unflatten = function( array, parent, tree ){
    tree = typeof tree !== 'undefined' ? tree : [];
    parent = typeof parent !== 'undefined' ? parent : { id: 0 };
        
    var children = _.filter( array, function(child){ return child.parentid == parent.id; });
    
    if( !_.isEmpty( children )  ){
        if( parent.id == 0 ){
           tree = children;   
        }else{
           parent['children'] = children
        }
        _.each( children, function( child ){ unflatten( array, child ) } );                    
    }
    
    return tree;
}

tree = unflatten( arr );
document.body.innerHTML = "<pre>" + (JSON.stringify(tree, null, " "))
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

आवश्यकताएँ

यह गुण 'आईडी' और 'पेरेंटिड' क्रमशः आईडी और अभिभावक आईडी को दर्शाता है। मूल आईडी 0 के साथ तत्व होने चाहिए, अन्यथा आपको एक खाली सरणी वापस मिलती है। अनाथ तत्व और उनके वंशज 'खो गए'

http://jsfiddle.net/LkkwH/1/


4
आप else { parent['children'] = []; }पहले इफ-क्लॉज के बाद जोड़ सकते हैं कि यह सुनिश्चित करने के लिए कि प्रत्येक नोड में एक विशेषता है children(यह खाली होगा यदि नोड एक पत्ती नोड है)
क्रिस्टोफर

2
आपका कोड स्निपेट पूरी तरह से काम करता है, धन्यवाद !! केवल एक चीज है: treeफ़ंक्शन को पुनरावर्ती रूप से कॉल करते समय एक तर्क के रूप में कभी भी पारित नहीं किया जाता है, इसलिए मुझे लगता है कि लाइन tree = typeof tree !== 'undefined' ? tree : [];को प्रतिस्थापित किया जा सकता हैlet tree = [];
ऑस्कर काल्डेरन

क्या इसे null0 के बजाय parent_ids की अनुमति देने के लिए संशोधित किया जा सकता है ? संपादित करें: कोई बात नहीं, मैं इसे बदल कर काम कर मिल गया id: 0के लिए id: null
dlinx90

ध्यान रखें कि उपरोक्त उत्तर दो छोरों का उपयोग करता है, और इसलिए सुधार किया जा सकता है। चूंकि मुझे एक एनपीएम मॉड्यूल नहीं मिला है जो ओ (एन) समाधान लागू करता है, मैंने निम्नलिखित एक (इकाई परीक्षण, 100% कोड कवरेज, केवल 0.5 केबी आकार में और टाइपिंग शामिल है) बनाया। शायद यह किसी की मदद करता है: npmjs.com/package/performant-array-to-tree
फिलिप स्टैनिस्लॉस

4
रुचि रखने वाले किसी व्यक्ति के लिए, कोड आसानी से वेनिला js में बदल जाता है: jsfiddle.net/LkkwH/853
xec

48

(BONUS1: NODES MAY or MAY Not BE ORDERED)

(BONUS2: NO 3RD PARTY LIBRARY की आवश्यकता है, PLAIN JS)

(BONUS3: उपयोगकर्ता "इलायस रब्बल" का कहना है कि यह सबसे तेज़ समाधान है, नीचे उसका उत्तर देखें)

यह रहा:

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

यहां एक परीक्षण है, यह आपको यह समझने में मदद कर सकता है कि समाधान कैसे काम करता है:

it('creates a correct shape of dataTree', () => {

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

    let 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)
});

2
यदि हम childNodesकेवल जरूरत पड़ने पर इसे जोड़ते हैं तो क्या यह अधिक सटीक नहीं होगा ? पहले से उन्हें हटाकर forEachदूसरे के अंदर ले जाकर?
arpl

@ हार्प सहमत हो गए। आवश्यकता होने पर व्यक्ति आसानी से बदल सकता है। या यदि आपको लगता है कि यह डिफ़ॉल्ट होना चाहिए, तो मैं इसे बदल सकता हूं।
फुरकानो

@ फरकानो वास्तव में अच्छा समाधान है, हालांकि यह कार्यात्मक प्रोग्रामिंग (कोई म्यूटेशन) के साथ इस प्रदर्शन के पास कहीं भी प्राप्त करना संभव होगा
Dac0d3r

34

एक ही समस्या थी, लेकिन मैं निश्चित नहीं हो सकता था कि डेटा सॉर्ट किया गया था या नहीं । मैं 3rd पार्टी लाइब्रेरी का उपयोग नहीं कर सकता था, इसलिए यह सिर्फ वनीला जेएस है; इनपुट डेटा @ स्टीफन के उदाहरण से लिया जा सकता है;

 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, " "))

जेएस फिडल

पेड़ के समीप का फ्लैट


कुछ मामलों mappedArr[mappedElem['parentid']]['children']में असफल रहा था क्योंकि childrenअपरिभाषित तक पहुँच नहीं कर सकता था ।
अल-मोताफ़र

मैं मूल आईडी पर कैसे शुरू करूंगा: 1?
विन्नी

31

इस ES6 दृष्टिकोण का उपयोग करें। आकर्षण की तरह काम करता है

// 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 => item[link] === id)
    .map(item => ({ ...item, children: nest(items, item.id) }));

console.log(
  nest(comments)
)


3
सबसे छोटा और सबसे अच्छा जवाब मुझे लगता है
जावा-मैन-स्क्रिप्ट

2
फुरकानो के जवाब की तुलना में स्लोगन
तुरी

16

एक और अधिक सरल फ़ंक्शन सूची-टू-ट्री-लाइट

npm install list-to-tree-lite

listToTree(list)

स्रोत:

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


10

आप इस प्रश्न को केवल दो लाइन कोडिंग से संभाल सकते हैं:

_(flatArray).forEach(f=>
           {f.nodes=_(flatArray).filter(g=>g.parentId==f.id).value();});

var resultArray=_(flatArray).filter(f=>f.parentId==null).value();

ऑनलाइन परीक्षण करें (बनाए गए पेड़ के लिए ब्राउज़र कंसोल देखें)

आवश्यकताएँ:

1- लश 4 स्थापित करें (प्रदर्शनकारी तरीकों के साथ वस्तुओं और संग्रह में हेरफेर करने के लिए एक जावास्क्रिप्ट पुस्तकालय => सी में लिनक की तरह )

2- नीचे की तरह एक फ्लैट:

    var flatArray=
    [{
      id:1,parentId:null,text:"parent1",nodes:[]
    }
   ,{
      id:2,parentId:null,text:"parent2",nodes:[]
    }
    ,
    {
      id:3,parentId:1,text:"childId3Parent1",nodes:[]
    }
    ,
    {
      id:4,parentId:1,text:"childId4Parent1",nodes:[]
    }
    ,
    {
      id:5,parentId:2,text:"childId5Parent2",nodes:[]
    }
    ,
    {
      id:6,parentId:2,text:"childId6Parent2",nodes:[]
    }
    ,
    {
      id:7,parentId:3,text:"childId7Parent3",nodes:[]
    }
    ,
    {
      id:8,parentId:5,text:"childId8Parent5",nodes:[]
    }];

श्री बख्शबाड़ी को धन्यवाद

सौभाग्य


8

यह उपयोगी पैकेज सूची-टू-ट्री इंस्टॉल हो सकता है :

bower install list-to-tree --save

या

npm install list-to-tree --save

उदाहरण के लिए, सूची है:

var list = [
  {
    id: 1,
    parent: 0
  }, {
    id: 2,
    parent: 1
  }, {
    id: 3,
    parent: 1
  }, {
    id: 4,
    parent: 2
  }, {
    id: 5,
    parent: 2
  }, {
    id: 6,
    parent: 0
  }, {
    id: 7,
    parent: 0
  }, {
    id: 8,
    parent: 7
  }, {
    id: 9,
    parent: 8
  }, {
    id: 10,
    parent: 0
  }
];

पैकेज सूची-इन-ट्री का उपयोग करें:

var ltt = new LTT(list, {
  key_id: 'id',
  key_parent: 'parent'
});
var tree = ltt.GetTree();

परिणाम:

[{
  "id": 1,
  "parent": 0,
  "child": [
    {
      "id": 2,
      "parent": 1,
      "child": [
        {
          "id": 4,
          "parent": 2
        }, {
          "id": 5, "parent": 2
        }
      ]
    },
    {
      "id": 3,
      "parent": 1
    }
  ]
}, {
  "id": 6,
  "parent": 0
}, {
  "id": 7,
  "parent": 0,
  "child": [
    {
      "id": 8,
      "parent": 7,
      "child": [
        {
          "id": 9,
          "parent": 8
        }
      ]
    }
  ]
}, {
  "id": 10,
  "parent": 0
}];

1
ध्यान दें कि लिंक-केवल उत्तर हतोत्साहित किए जाते हैं, एसओ उत्तर एक समाधान के लिए खोज का अंतिम बिंदु होना चाहिए (बनाम संदर्भों का एक और ठहराव, जो समय के साथ बासी हो जाते हैं)। कृपया एक स्टैंड-अलोन सिनॉप्सिस जोड़ने पर विचार करें, लिंक को संदर्भ के रूप में रखते हुए
kleopatra

मुझे समझ में नहीं आता कि क्यों -1, मुझे लगता है कि यह एक अच्छा समाधान है, लेकिन दुर्भाग्य से मैं पैकेज को gitHub या किसी अन्य सार्वजनिक रिपॉजिटरी में नहीं
ढूंढता

पैकेज पर ध्यान देने के लिए आपका धन्यवाद। मैंने बाद में इसका विस्तार करने की योजना बनाई। यहाँ भंडार के लिए एक लिंक है github.com/DenQ/list-to-tree
DenQ

@ योरोज मुझे खुशी है कि परियोजना से लाभ हुआ। कुछ विचारों की योजना
डेनक्यू

अच्छी तरह से काम करता है, धन्यवाद @DenQ। काश इसका अधिक परीक्षण कवरेज होता!
इलियास

3

मैंने दो सबसे सामान्य समाधानों के प्रदर्शन का मूल्यांकन करने के लिए एक परीक्षण स्क्रिप्ट लिखी है (जिसका अर्थ है कि इनपुट को पहले से सॉर्ट नहीं करना है और यह कि कोड तीसरे पक्ष के पुस्तकालयों पर निर्भर नहीं करता है), उपयोगकर्ताओं द्वारा प्रस्तावित shekhardtu ( उत्तर देखें ) और फुरकानो ( उत्तर देखें )।

http://playcode.io/316025?tabs=console&script.js&output

फुरकानो का हल सबसे तेज लगता है।

/*
** performance test for /programming/18017869/build-tree-array-from-flat-array-in-javascript
*/

// Data Set (e.g. nested comments)
var comments = [{
    id: 1,
    parent_id: null
}, {
    id: 2,
    parent_id: 1
}, {
    id: 3,
    parent_id: 4
}, {
    id: 4,
    parent_id: null
}, {
    id: 5,
    parent_id: 4
}];

// add some random entries
let maxParentId = 10000;
for (let i=6; i<=maxParentId; i++)
{
  let randVal = Math.floor((Math.random() * maxParentId) + 1);
  comments.push({
    id: i,
    parent_id: (randVal % 200 === 0 ? null : randVal)
  });
}

// solution from user "shekhardtu" (https://stackoverflow.com/a/55241491/5135171)
const nest = (items, id = null, link = 'parent_id') =>
  items
    .filter(item => item[link] === id)
    .map(item => ({ ...item, children: nest(items, item.id) }));
;

// solution from user "FurkanO" (https://stackoverflow.com/a/40732240/5135171)
const createDataTree = dataset => {
    let hashTable = Object.create(null)
    dataset.forEach( aData => hashTable[aData.id] = { ...aData, children : [] } )
    let dataTree = []
    dataset.forEach( aData => {
      if( aData.parent_id ) hashTable[aData.parent_id].children.push(hashTable[aData.id])
      else dataTree.push(hashTable[aData.id])
    } )
    return dataTree
};


/*
** lets evaluate the timing for both methods
*/
let t0 = performance.now();
let createDataTreeResult = createDataTree(comments);
let t1 = performance.now();
console.log("Call to createDataTree took " + Math.floor(t1 - t0) + " milliseconds.");

t0 = performance.now();
let nestResult = nest(comments);
t1 = performance.now();
console.log("Call to nest took " + Math.floor(t1 - t0) + " milliseconds.");




//console.log(nestResult);
//console.log(createDataTreeResult);

// bad, but simple way of comparing object equality
console.log(JSON.stringify(nestResult)===JSON.stringify(createDataTreeResult));


2

यह अव्यवस्थित वस्तुओं के लिए एक प्रस्ताव है। यह फ़ंक्शन एक लूप के साथ और एक हैश टेबल के साथ काम करता है और उनके साथ सभी आइटम एकत्र करता है id। यदि रूट नोड पाया जाता है, तो ऑब्जेक्ट को परिणाम सरणी में जोड़ा जाता है।

function getTree(data, root) {
    var o = {};
    data.forEach(function (a) {
        if (o[a.id] && o[a.id].children) {
            a.children = o[a.id].children;
        }
        o[a.id] = a;
        o[a.parentId] = o[a.parentId] || {};
        o[a.parentId].children = o[a.parentId].children || [];
        o[a.parentId].children.push(a);
    });
    return o[root].children;
}

var data = { 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 }] },
    tree = Object.keys(data).reduce(function (r, k) {
        r[k] = getTree(data[k], '0');
        return r;
    }, {});

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }


1

यह भी lodashjs (v4.x) के साथ करते हैं

function buildTree(arr){
  var a=_.keyBy(arr, 'id')
  return _
   .chain(arr)
   .groupBy('parentId')
   .forEach(function(v,k){ 
     k!='0' && (a[k].children=(a[k].children||[]).concat(v));
   })
   .result('0')
   .value();
}

1

मुझे @ विलियमलेंग का शुद्ध जावास्क्रिप्ट समाधान पसंद है, लेकिन कभी-कभी आपको ऑब्जेक्ट का संदर्भ रखने के लिए मौजूदा सरणी में परिवर्तन करने की आवश्यकता होती है।

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 item, id, parentId;
  var map = {};
    for(var i = 0; i < data.length; i++ ) { // make cache
    if(data[i][ID_KEY]){
      map[data[i][ID_KEY]] = data[i];
      data[i][CHILDREN_KEY] = [];
    }
  }
  for (var i = 0; i < data.length; i++) {
    if(data[i][PARENT_KEY]) { // is a child
      if(map[data[i][PARENT_KEY]]) // for dirty data
      {
        map[data[i][PARENT_KEY]][CHILDREN_KEY].push(data[i]); // add child to parent
        data.splice( i, 1 ); // remove from root
        i--; // iterator correction
      } else {
        data[i][PARENT_KEY] = 0; // clean dirty data
      }
    }
  };
  return data;
}

निर्गमन: https://jsfiddle.net/kqw1qsf0/17/


1

var data = [{"country":"india","gender":"male","type":"lower","class":"X"},
			{"country":"china","gender":"female","type":"upper"},
			{"country":"india","gender":"female","type":"lower"},
			{"country":"india","gender":"female","type":"upper"}];
var seq = ["country","type","gender","class"];
var treeData = createHieArr(data,seq);
console.log(treeData)
function createHieArr(data,seq){
	var hieObj = createHieobj(data,seq,0),
		hieArr = convertToHieArr(hieObj,"Top Level");
		return [{"name": "Top Level", "parent": "null",
				     "children" : hieArr}]
	function convertToHieArr(eachObj,parent){
		var arr = [];
		for(var i in eachObj){
			arr.push({"name":i,"parent":parent,"children":convertToHieArr(eachObj[i],i)})
		}
		return arr;
	}
	function createHieobj(data,seq,ind){
		var s = seq[ind];
		if(s == undefined){
			return [];
		}
		var childObj = {};
		for(var ele of data){
			if(ele[s] != undefined){
				if(childObj[ele[s]] == undefined){
					childObj[ele[s]] = [];
				}
				childObj[ele[s]].push(ele);
			}
		}
		ind = ind+1;
		for(var ch in childObj){
			childObj[ch] = createHieobj(childObj[ch],seq,ind)
		}
		return childObj;
	}
}


मैंने इस फ़ंक्शन को ऑब्जेक्ट की सरणी से ट्री संरचना में डेटा परिवर्तित करने के लिए बनाया है, जो कि d3 ट्री इंटरेक्टिव चार्ट के लिए आवश्यक है। कोड की केवल 40 पंक्तियों के साथ मैं आउटपुट प्राप्त करने में सक्षम था। मैंने इस फ़ंक्शन को प्रभावी ढंग से js में पुनरावर्ती funtionality usign किया। कोशिश करें और मुझे अपनी प्रतिक्रिया दें। धन्यवाद!!!!
कार्तिक रेड्डी

Awser के लिए धन्यवाद..यह मेरे d3 ट्री टोपोलॉजी के लिए पूरी तरह से काम करता है .. अब मुझे आवश्यकता है कि मुझे नोड के मूल्यों के आधार पर नोड रंग को बदलने की आवश्यकता है। इसके लिए मुझे JSON में एक ध्वज मान को पास करने की आवश्यकता है । मैं कैसे करूँ .. {"नाम": "शीर्ष स्तर", "झंडा": 1, "माता-पिता": "अशक्त", "बच्चे": [{"नाम": "भारत", "झंडा": 0 , "माता-पिता": "शीर्ष स्तर", "बच्चे": [
पुनीत कुमार

1

Npm पैकेज ट्री- यूज़ पर आपकी नज़र हो सकती है यदि आप SQL DB डेटा टेबल से डेटा लोड करना चाहते हैं तो यह बहुत आसान भी हो सकता है। आप आसानी से बनाए गए पेड़ में नोड्स में अतिरिक्त डेटा भी जोड़ सकते हैं।

अस्वीकरण, मैंने यह पैकेज बनाया।


1

मेरे पास कुछ दिन पहले ऐसा ही मुद्दा था जब फ्लैट ऐरे से फोल्डर ट्री प्रदर्शित करना था। मुझे यहां टाइपस्क्रिप्ट में कोई समाधान नहीं दिखाई दिया, इसलिए मुझे उम्मीद है कि यह उपयोगी होगा।

मेरे मामलों में मुख्य माता-पिता केवल एक ही थे, रॉडेटा सरणी को भी सॉर्ट करने की आवश्यकता नहीं है। सॉल्यूशन बेस ऑन टेम्प टेम्प ऑब्जेक्ट जैसे {parentId: [child1, child2, ...] }

उदाहरण कच्चे डेटा

const flatData: any[] = Folder.ofCollection([
  {id: '1', title: 'some title' },
  {id: '2', title: 'some title', parentId: 1 },
  {id: '3', title: 'some title', parentId: 7 },
  {id: '4', title: 'some title', parentId: 1 },
  {id: '5', title: 'some title', parentId: 2 },
  {id: '6', title: 'some title', parentId: 5 },
  {id: '7', title: 'some title', parentId: 5 },

]);

फोल्डर का दोष

export default class Folder {
    public static of(data: any): Folder {
        return new Folder(data);
    }

    public static ofCollection(objects: any[] = []): Folder[] {
        return objects.map((obj) => new Folder(obj));
    }

    public id: string;
    public parentId: string | null;
    public title: string;
    public children: Folder[];

    constructor(data: any = {}) {
        this.id = data.id;
        this.parentId = data.parentId || null;
        this.title = data.title;
        this.children = data.children || [];
    }
}

समाधान : फ़ंक्शन जो फ्लैट तर्क के लिए ट्री संरचना देता है

    public getTree(flatData: any[]): Folder[] {
        const addChildren = (item: Folder) => {
            item.children = tempChild[item.id] || [];
            if (item.children.length) {
                item.children.forEach((child: Folder) => {
                    addChildren(child);
                });
            }
        };

        const tempChild: any = {};
        flatData.forEach((item: Folder) => {
            const parentId = item.parentId || 0;
            Array.isArray(tempChild[parentId]) ? tempChild[parentId].push(item) : (tempChild[parentId] = [item]);
        });

        const tree: Folder[] = tempChild[0];
        tree.forEach((base: Folder) => {
            addChildren(base);
        });
        return tree;
    }

0

यहाँ एक सरल सहायक कार्य है, जिसे मैंने उपरोक्त उत्तरों के बाद बनाया है, एक बैबल वातावरण के अनुरूप:

import { isEmpty } from 'lodash'

export default function unflattenEntities(entities, parent = {id: null}, tree = []) {

  let children = entities.filter( entity => entity.parent_id == parent.id)

  if (!isEmpty( children )) {
    if ( parent.id == null ) {
      tree = children
    } else {
      parent['children'] = children
    }
    children.map( child => unflattenEntities( entities, child ) )
  }

  return tree

}

0

यहां स्टीवन हैरिस का एक संशोधित संस्करण है, जो सादा ईएस 5 है और शीर्ष स्तर पर और बच्चों के लिए नोड्स के एक सरणी को वापस करने के बजाय आईडी पर बंद किए गए ऑब्जेक्ट को लौटाता है।

unflattenToObject = function(array, parent) {
  var tree = {};
  parent = typeof parent !== 'undefined' ? parent : {id: 0};

  var childrenArray = array.filter(function(child) {
    return child.parentid == parent.id;
  });

  if (childrenArray.length > 0) {
    var childrenObject = {};
    // Transform children into a hash/object keyed on token
    childrenArray.forEach(function(child) {
      childrenObject[child.id] = child;
    });
    if (parent.id == 0) {
      tree = childrenObject;
    } else {
      parent['children'] = childrenObject;
    }
    childrenArray.forEach(function(child) {
      unflattenToObject(array, child);
    })
  }

  return tree;
};

var arr = [
    {'id':1 ,'parentid': 0},
    {'id':2 ,'parentid': 1},
    {'id':3 ,'parentid': 1},
    {'id':4 ,'parentid': 2},
    {'id':5 ,'parentid': 0},
    {'id':6 ,'parentid': 0},
    {'id':7 ,'parentid': 4}
];
tree = unflattenToObject(arr);

0

यह ऊपर का एक संशोधित संस्करण है जो कई रूट आइटमों के साथ काम करता है, मैं अपने आईडी और पेरेंट के लिए GUID का उपयोग करता हूं ताकि UI में ऐसा हो जो मुझे 0000000-00000-00000-TREE-ROOT-ITEM जैसे कुछ के लिए हार्ड कोड रूट आइटम बनाता है।

var tree = unflatten (रिकॉर्ड, "TREE-ROOT-ITEM");

function unflatten(records, rootCategoryId, parent, tree){
    if(!_.isArray(tree)){
        tree = [];
        _.each(records, function(rec){
            if(rec.parentId.indexOf(rootCategoryId)>=0){        // change this line to compare a root id
            //if(rec.parentId == 0 || rec.parentId == null){    // example for 0 or null
                var tmp = angular.copy(rec);
                tmp.children = _.filter(records, function(r){
                    return r.parentId == tmp.id;
                });
                tree.push(tmp);
                //console.log(tree);
                _.each(tmp.children, function(child){
                    return unflatten(records, rootCategoryId, child, tree);
                });
            }
        });
    }
    else{
        if(parent){
            parent.children = _.filter(records, function(r){
                return r.parentId == parent.id;
            });
            _.each(parent.children, function(child){
                return unflatten(records, rootCategoryId, child, tree);
            });
        }
    }
    return tree;
}

0

इंटरनेट से कॉपी किया गया http://jsfiddle.net/stywell/k9x2a3g6/

    function list2tree(data, opt) {
        opt = opt || {};
        var KEY_ID = opt.key_id || 'ID';
        var KEY_PARENT = opt.key_parent || 'FatherID';
        var KEY_CHILD = opt.key_child || 'children';
        var EMPTY_CHILDREN = opt.empty_children;
        var ROOT_ID = opt.root_id || 0;
        var MAP = opt.map || {};
        function getNode(id) {
            var node = []
            for (var i = 0; i < data.length; i++) {
                if (data[i][KEY_PARENT] == id) {
                    for (var k in MAP) {
                        data[i][k] = data[i][MAP[k]];
                    }
                    if (getNode(data[i][KEY_ID]) !== undefined) {
                        data[i][KEY_CHILD] = getNode(data[i][KEY_ID]);
                    } else {
                        if (EMPTY_CHILDREN === null) {
                            data[i][KEY_CHILD] = null;
                        } else if (JSON.stringify(EMPTY_CHILDREN) === '[]') {
                            data[i][KEY_CHILD] = [];
                        }
                    }
                    node.push(data[i]);
                }
            }
            if (node.length == 0) {
                return;
            } else {
                return node;
            }
        }
        return getNode(ROOT_ID)
    }

    var opt = {
        "key_id": "ID",              //节点的ID
        "key_parent": "FatherID",    //节点的父级ID
        "key_child": "children",     //子节点的名称
        "empty_children": [],        //子节点为空时,填充的值  //这个参数为空时,没有子元素的元素不带key_child属性;还可以为null或者[],同理
        "root_id": 0,                //根节点的父级ID
        "map": {                     //在节点内映射一些值  //对象的键是节点的新属性; 对象的值是节点的老属性,会赋值给新属性
            "value": "ID",
            "label": "TypeName",
        }
    };

0

आप npm पैकेज सरणी-टू-ट्री https://github.com/alferov/array-to-tree का उपयोग कर सकते हैं । यह एक नेस्टेड डेटा संरचना में नोड्स के एक सादे सरणी को (अभिभावकों को मूल नोड्स के साथ) में परिवर्तित करता है।

डेटा के डेटाबेस सेट से पुनर्प्राप्त किए गए रूपांतरण के साथ एक समस्या को नेस्टेड डेटा संरचना (यानी नेविगेशन ट्री) में हल करता है।

उपयोग:

var arrayToTree = require('array-to-tree');

var dataOne = [
  {
    id: 1,
    name: 'Portfolio',
    parent_id: undefined
  },
  {
    id: 2,
    name: 'Web Development',
    parent_id: 1
  },
  {
    id: 3,
    name: 'Recent Works',
    parent_id: 2
  },
  {
    id: 4,
    name: 'About Me',
    parent_id: undefined
  }
];

arrayToTree(dataOne);

/*
 * Output:
 *
 * Portfolio
 *   Web Development
 *     Recent Works
 * About Me
 */

0

यह वही है जो मैंने एक प्रतिक्रिया परियोजना में उपयोग किया है

// ListToTree.js
import _filter from 'lodash/filter';
import _map from 'lodash/map';

export default (arr, parentIdKey) => _map(_filter(arr, ar => !ar[parentIdKey]), ar => ({
  ...ar,
  children: _filter(arr, { [parentIdKey]: ar.id }),
}));

उपयोग:

// somewhere.js
import ListToTree from '../Transforms/ListToTree';

const arr = [
   {
      "id":"Bci6XhCLZKPXZMUztm1R",
      "name":"Sith"
   },
   {
      "id":"C3D71CMmASiR6FfDPlEy",
      "name":"Luke",
      "parentCategoryId":"ltatOlEkHdVPf49ACCMc"
   },
   {
      "id":"aS8Ag1BQqxkO6iWBFnsf",
      "name":"Obi Wan",
      "parentCategoryId":"ltatOlEkHdVPf49ACCMc"
   },
   {
      "id":"ltatOlEkHdVPf49ACCMc",
      "name":"Jedi"
   },
   {
      "id":"pw3CNdNhnbuxhPar6nOP",
      "name":"Palpatine",
      "parentCategoryId":"Bci6XhCLZKPXZMUztm1R"
   }
];
const response = ListToTree(arr, 'parentCategoryId');

उत्पादन:

[
   {
      "id":"Bci6XhCLZKPXZMUztm1R",
      "name":"Sith",
      "children":[
         {
            "id":"pw3CNdNhnbuxhPar6nOP",
            "name":"Palpatine",
            "parentCategoryId":"Bci6XhCLZKPXZMUztm1R"
         }
      ]
   },
   {
      "id":"ltatOlEkHdVPf49ACCMc",
      "name":"Jedi",
      "children":[
         {
            "id":"C3D71CMmASiR6FfDPlEy",
            "name":"Luke",
            "parentCategoryId":"ltatOlEkHdVPf49ACCMc"
         },
         {
            "id":"aS8Ag1BQqxkO6iWBFnsf",
            "name":"Obi Wan",
            "parentCategoryId":"ltatOlEkHdVPf49ACCMc"
         }
      ]
   }
]```


0

मेरे टाइपस्क्रिप्ट समाधान, शायद यह आपकी मदद करता है:

type ITreeItem<T> = T & {
    children: ITreeItem<T>[],
};

type IItemKey = string | number;

function createTree<T>(
    flatList: T[],
    idKey: IItemKey,
    parentKey: IItemKey,
): ITreeItem<T>[] {
    const tree: ITreeItem<T>[] = [];

    // hash table.
    const mappedArr = {};
    flatList.forEach(el => {
        const elId: IItemKey = el[idKey];

        mappedArr[elId] = el;
        mappedArr[elId].children = [];
    });

    // also you can use Object.values(mappedArr).forEach(...
    // but if you have element which was nested more than one time
    // you should iterate flatList again:
    flatList.forEach((elem: ITreeItem<T>) => {
        const mappedElem = mappedArr[elem[idKey]];

        if (elem[parentKey]) {
            mappedArr[elem[parentKey]].children.push(elem);
        } else {
            tree.push(mappedElem);
        }
    });

    return tree;
}

उपयोग का उदाहरण:

createTree(yourListData, 'id', 'parentId');

0

मैंने @Halcyon उत्तर के आधार पर ES6 संस्करण लिखा

const array = [
  {
    id: '12',
    parentId: '0',
    text: 'one-1'
  },
  {
    id: '6',
    parentId: '12',
    text: 'one-1-6'
  },
  {
    id: '7',
    parentId: '12',
    text: 'one-1-7'
  },

  {
    id: '9',
    parentId: '0',
    text: 'one-2'
  },
  {
    id: '11',
    parentId: '9',
    text: 'one-2-11'
  }
];

// Prevent changes to the original data
const arrayCopy = array.map(item => ({ ...item }));

const listToTree = list => {
  const map = {};
  const roots = [];

  list.forEach((v, i) => {
    map[v.id] = i;
    list[i].children = [];
  });

  list.forEach(v => (v.parentId !== '0' ? list[map[v.parentId]].children.push(v) : roots.push(v)));

  return roots;
};

console.log(listToTree(arrayCopy));

इस एल्गोरिथ्म का सिद्धांत सूचकांक संबंध स्थापित करने के लिए "मानचित्र" का उपयोग करना है। "पेरेंटआईड" द्वारा सूची में "आइटम" ढूंढना आसान है, और प्रत्येक "आइटम" में "बच्चे" जोड़ें, क्योंकि "सूची" एक संदर्भ संबंध है, इसलिए "जड़ें" पूरे पेड़ के साथ संबंध बनाएंगी।


0

एक समान प्रश्न का उत्तर:

https://stackoverflow.com/a/61575152/7388356

अपडेट करें

आप उपयोग कर सकते हैं Map ES6 में पेश की गई वस्तु का । मूल रूप से फिर से सरणी पर माता-पिता को ढूंढने के बजाय, आपको बस माता-पिता की आईडी द्वारा सरणी से मूल आइटम मिल जाएगा जैसे कि आप सूचकांक द्वारा एक सरणी में आइटम प्राप्त करते हैं।

यहाँ सरल उदाहरण है:

const 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
  }
];

function toTree(arr) {
  let arrMap = new Map(arr.map(item => [item.id, item]));
  let tree = [];

  for (let i = 0; i < arr.length; i++) {
    let item = arr[i];

    if (item.parentId !== "0") {
      let parentItem = arrMap.get(item.parentId);

      if (parentItem) {
        let { children } = parentItem;

        if (children) {
          parentItem.children.push(item);
        } else {
          parentItem.children = [item];
        }
      }
    } else {
      tree.push(item);
    }
  }

  return tree;
}

let tree = toTree(people);

console.log(tree);

क्रेज़ी-विलियम्स-ग्लग्ज 3 संपादित करें


1
हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं। - रिव्यू से
जेफरीसन

ठीक है, मुख्य विचार जोड़ा गया और एक नमूना उदाहरण दिया,
यूसुफबेक

0

@ फुरकानो के उत्तर के आधार पर , मैंने एक और संस्करण बनाया जो मूल डेटा को म्यूट नहीं करता है (जैसे @ Dac0d3r अनुरोधित)। मुझे वास्तव में @ shekhardtu का उत्तर पसंद आया , लेकिन यह महसूस किया कि इसे कई बार डेटा को फ़िल्टर करना पड़ा। मैंने सोचा कि पहले डेटा की प्रतिलिपि बनाकर फुरकानो के उत्तर का उपयोग किया जा सकता है। मैंने अपने संस्करण को jsperf में आज़माया , और परिणाम जहाँ दुर्भाग्य से (बहुत) धूमिल होते हैं ... ऐसा लगता है कि स्वीकृत उत्तर वास्तव में एक अच्छा है! मेरा संस्करण हालांकि काफी विन्यास योग्य और विफल है, इसलिए मैं इसे आप लोगों के साथ वैसे भी साझा करता हूं; यहाँ मेरा योगदान है:

function unflat(data, options = {}) {
    const { id, parentId, childrenKey } = {
        id: "id",
        parentId: "parentId",
        childrenKey: "children",
        ...options
    };
    const copiesById = data.reduce(
        (copies, datum) => ((copies[datum[id]] = datum) && copies),
        {}
    );
    return Object.values(copiesById).reduce(
        (root, datum) => {
            if ( datum[parentId] && copiesById[datum[parentId]] ) {
                copiesById[datum[parentId]][childrenKey] = [ ...copiesById[datum[parentId]][childrenKey], datum ];
            } else {
                root = [ ...root, datum ];
            }
            return root
        }, []
    );
}

const data = [
    {
        "account": "10",
        "name": "Konto 10",
        "parentAccount": null
    },{
        "account": "1010",
        "name": "Konto 1010",
        "parentAccount": "10"
    },{
        "account": "10101",
        "name": "Konto 10101",
        "parentAccount": "1010"
    },{
        "account": "10102",
        "name": "Konto 10102",
        "parentAccount": "1010"
    },{
        "account": "10103",
        "name": "Konto 10103",
        "parentAccount": "1010"
    },{
        "account": "20",
        "name": "Konto 20",
        "parentAccount": null
    },{
        "account": "2020",
        "name": "Konto 2020",
        "parentAccount": "20"
    },{
        "account": "20201",
        "name": "Konto 20201",
        "parentAccount": "2020"
    },{
        "account": "20202",
        "name": "Konto 20202",
        "parentAccount": "2020"
    }
];

const options = {
    id: "account",
    parentId: "parentAccount",
    childrenKey: "children"
};

console.log(
    "Hierarchical tree",
    unflat(data, options)
);

विकल्प पैरामीटर के साथ, यह संभव है कि किस संपत्ति को आईडी या मूल आईडी के रूप में उपयोग किया जाए। बच्चों की संपत्ति के नाम को कॉन्फ़िगर करना भी संभव है, अगर कोई चाहता है "childNodes": []या कुछ और।

ओपी बस डिफ़ॉल्ट विकल्प का उपयोग कर सकता है:

input.People = unflat(input.People);

पैरेंट आईडी falsy (है null, undefinedया अन्य falsy मान) या पैरेंट ऑब्जेक्ट अस्तित्व में नहीं है, तो हम वस्तु पर विचार एक रूट नोड किया जाना है।


-1
  1. थर्ड पार्टी लाइब्रेरी के बिना
  2. पूर्व-क्रम सरणी के लिए कोई ज़रूरत नहीं है
  3. आप मनचाहे पेड़ का कोई भी हिस्सा प्राप्त कर सकते हैं

इसे इस्तेमाल करे

function getUnflatten(arr,parentid){
  let output = []
  for(const obj of arr){
    if(obj.parentid == parentid)

      let children = getUnflatten(arr,obj.id)

      if(children.length){
        obj.children = children
      }
      output.push(obj)
    }
  }

  return output
 }

इसे Jsfiddle पर टेस्ट करें


-1

कनवर्ट करें नोड्स ट्री के लिए

ES6 फ़ंक्शन नोड के एक सरणी को बदलने के लिए ( मूल आईडी से संबंधित ) - एक ट्री संरचना के लिए:

/**
 * Convert nodes list related by parent ID - to tree.
 * @syntax getTree(nodesArray [, rootID [, propertyName]])
 *
 * @param {Array} arr   Array of nodes
 * @param {integer} id  Defaults to 0
 * @param {string} p    Property name. Defaults to "parent_id"
 * @returns {Object}    Nodes tree
 */

const getTree = (arr, p = "parent_id") => arr.reduce((o, n) => {

  if (!o[n.id]) o[n.id] = {};
  if (!o[n[p]]) o[n[p]] = {};
  if (!o[n[p]].nodes) o[n[p]].nodes= [];
  if (o[n.id].nodes) n.nodes= o[n.id].nodes;

  o[n[p]].nodes.push(n);
  o[n.id] = n;

  return o;
}, {});

नोड्स ट्री से HTML सूची बनाएं

जगह में हमारे पेड़ होने, यहाँ उल> एलआई तत्वों का निर्माण करने के लिए एक पुनरावर्ती कार्य है:

/**
 * Convert Tree structure to UL>LI and append to Element
 * @syntax getTree(treeArray [, TargetElement [, onLICreatedCallback ]])
 *
 * @param {Array} tree Tree array of nodes
 * @param {Element} el HTMLElement to insert into
 * @param {function} cb Callback function called on every LI creation
 */

const treeToHTML = (tree, el, cb) => el.append(tree.reduce((ul, n) => {
  const li = document.createElement('li');

  if (cb) cb.call(li, n);
  if (n.nodes?.length) treeToHTML(n.nodes, li, cb);

  ul.append(li);
  return ul;
}, document.createElement('ul')));

डेमो समय

यहाँ एक उदाहरण है, नोड्स का एक लीनियर ऐरे और उपरोक्त दोनों फंक्शन का उपयोग करना:

const getTree = (arr, p = "parent_id") => arr.reduce((o, n) => {
  if (!o[n.id]) o[n.id] = {};
  if (!o[n[p]]) o[n[p]] = {};
  if (!o[n[p]].nodes) o[n[p]].nodes = [];
  if (o[n.id].nodes) n.nodes = o[n.id].nodes;
  o[n[p]].nodes.push(n);
  o[n.id] = n;
  return o;
}, {});


const treeToHTML = (tree, el, cb) => el.append(tree.reduce((ul, n) => {
  const li = document.createElement('li');
  if (cb) cb.call(li, n);
  if (n.nodes?.length) treeToHTML(n.nodes, li, cb);
  ul.append(li);
  return ul;
}, document.createElement('ul')));


// DEMO TIME:

const nodesList = [
  {id: 10,  parent_id: 4,  text: "Item 10"}, // PS: Order does not matters
  {id: 1,   parent_id: 0,  text: "Item 1"},  
  {id: 4,   parent_id: 0,  text: "Item 4"},
  {id: 3,   parent_id: 5,  text: "Item 3"},
  {id: 5,   parent_id: 4,  text: "Item 5"},
  {id: 2,   parent_id: 1,  text: "Item 2"},
];
const myTree = getTree(nodesList)[0].nodes; // Get nodes of Root (0)

treeToHTML(myTree, document.querySelector("#tree"), function(node) {
  this.textContent = `(${node.parent_id} ${node.id}) ${node.text}`;
  this._node = node;
  this.addEventListener('click', clickHandler);
});

function clickHandler(ev) {
  if (ev.target !== this) return;
  console.clear();
  console.log(this._node.id);
};
<div id="tree"></div>


-1

यह एक पुराना धागा है, लेकिन मुझे लगा कि एक अपडेट से कभी नुकसान नहीं होता, ES6 के साथ आप यह कर सकते हैं:

const data = [{
    id: 1,
    parent_id: 0
}, {
    id: 2,
    parent_id: 1
}, {
    id: 3,
    parent_id: 1
}, {
    id: 4,
    parent_id: 2
}, {
    id: 5,
    parent_id: 4
}, {
    id: 8,
    parent_id: 7
}, {
    id: 9,
    parent_id: 8
}, {
    id: 10,
    parent_id: 9
}];

const arrayToTree = (items=[], id = null, link = 'parent_id') => items.filter(item => id==null ? !items.some(ele=>ele.id===item[link]) : item[link] === id ).map(item => ({ ...item, children: arrayToTree(items, item.id) }))
const temp1=arrayToTree(data)
console.log(temp1)

const treeToArray = (items=[], key = 'children') => items.reduce((acc, curr) => [...acc, ...treeToArray(curr[key])].map(({ [`${key}`]: child, ...ele }) => ele), items);
const temp2=treeToArray(temp1)

console.log(temp2)

आशा है कि यह किसी की मदद करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.