জাভাস্ক্রিপ্টে ফ্ল্যাট অ্যারে থেকে ট্রি অ্যারে তৈরি করুন


134

আমার একটি জটিল জেসন ফাইল রয়েছে যা পরে জাভা স্ক্রিপ্ট সহ এটি হায়ারারিকালিকাল করতে আমাকে হ্যান্ডেল করতে হবে যাতে পরে একটি গাছ তৈরি করতে পারে। জসনের প্রতিটি প্রবেশে রয়েছে: আইডি: একটি অনন্য আইডি, প্যারেন্ট আইড: প্যারেন্ট নোডের আইডি (যা নোড গাছের মূল হয় তবে 0) স্তর: গাছের গভীরতার স্তর

জসন ডেটা ইতিমধ্যে "অর্ডার করা"। আমি বোঝাতে চাইছি যে একটি এন্ট্রিতে নিজের উপরে একটি প্যারেন্ট নোড বা ভাই নোড থাকবে এবং নিজের নীচে একটি শিশু নোড বা ভাই নোড থাকবে।

ইনপুট :

{
    "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
এটি করার বিভিন্ন উপায় রয়েছে, আপনি কি এখনও কিছু চেষ্টা করেছেন?
bfavareto

আমি ধরে নিই যে parentIdএর 0অর্থগুলির কোনও প্যারেন্ট আইডি নেই এবং এটি শীর্ষ স্তর হওয়া উচিত।
ডনি ডি'আমাটো

সাধারণত এই ধরণের কাজের জন্য বিস্তৃত কর্মক্ষম জ্ঞানের অবজেক্টগুলির প্রয়োজন হয়। ভাল প্রশ্ন
গঙ্গাধর জেএনএনএউ

উত্তর:


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 ^ 2) যা বড় ডেটা সেটগুলির জন্য সমস্যা হতে পারে।


28
মনে রাখবেন যে এই সমাধানের সাহায্যে আপনার নোডগুলিকে প্রথমে মানচিত্রে পিতামাতার দিকে ঠেলাঠেলি করা নিশ্চিত করার জন্য অবশ্যই বিশেষভাবে আদেশ করতে হবে, অন্যথায় অনুসন্ধানের প্রক্রিয়াটি ত্রুটিযুক্ত হবে ... সুতরাং আপনাকে স্তরের সম্পত্তিটির উপর ভাগ করে নেওয়া দরকার, অথবা আপনার প্রয়োজন এগুলি প্রথমে মানচিত্রে ঠেলাতে। এবং লুপের জন্য পৃথক পৃথক ব্যবহার করুন। (আপনার কাছে যখন কোনও স্তরের সম্পত্তি না থাকে তবে পৃথক লুপগুলির বিকল্প হতে পারে তবে আমি সাজানোর পছন্দ করি)
Sander

আমি প্রথমে অবাক করে দিয়েছি যে অতিরিক্ত তথ্য থাকা যেমন, [1, 5, 6] এর মতো একটি পথ যেখানে অ্যারেটি পরবর্তী পূর্বপুরুষ, সেখানে এটি দক্ষতার সাথে ব্যবহার করা যায়নি। তবে কোডটি দেখে এটুকু সংবেদনশীল হয়ে ওঠে যেহেতু আমি বিশ্বাস করি এটি হে (এন)
সিড

1
ভাল উত্তর সত্ত্বেও, এটি জটিল। মাত্র দুটি লাইন কোডের জন্য আমার উত্তরটি প্রয়োগ করুন: লিংক
ইমান বাহরামপুর ২

দয়া করে আপনি ব্যাখ্যা করতে পারেন কেন এই সমাধানটি Θ (n লগ (এন)), এটি O (n) সময় নিচ্ছে বলে মনে হচ্ছে।
amrender সিং

ফর্ম-লুপের ভিতরে @ অ্যামেরেন্ডারসিংহ হ্যাশ-লুচিংয়ে map(তত্ত্ব অনুসারে) ও (লগ এন)।
হালসিওন

72

@ স্যান্ডার দ্বারা উল্লিখিত হিসাবে, @ হালসিওনের উত্তর একটি পূর্ব-সাজানো অ্যারে ধরেছে, নিম্নলিখিতটি তা করে না। (তবে এটি ধরে নিয়েছে যে আপনি আন্ডারস্কোর.জেএস লোড করেছেন - যদিও এটি ভ্যানিলা জাভাস্ক্রিপ্টে লেখা যেতে পারে):

কোড

// 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'] = []; }প্রতিটি নোডের একটি বৈশিষ্ট্য রয়েছে তা নিশ্চিত করার জন্য আপনি প্রথম if-claus এর পরে যুক্ত করতে পারেন children(নোড একটি পাতা নোড হলে এটি খালি হবে)
ক্রিস্টোফার

2
আপনার কোড স্নিপেট পুরোপুরি কাজ করেছে, আপনাকে ধন্যবাদ !! একমাত্র বিষয়: treeফাংশনটিকে পুনরাবৃত্তভাবে কল করার সময় কোনও যুক্তি হিসাবে কখনই পাস হয় না, তাই আমি মনে করি লাইনটি tree = typeof tree !== 'undefined' ? tree : [];প্রতিস্থাপন করা যেতে পারেlet tree = [];
অস্কার ক্যাল্ডারন

nullএটি 0 এর পরিবর্তে প্যারেন্ট_আইডিকে অনুমতি দিতে সংশোধন করা যেতে পারে ? সম্পাদনা: কিছু মনে করবেন না, আমি এটা পরিবর্তন করে কাজ করতে দেখে id: 0কাছে id: null
dlinx90

মনে রাখবেন যে উপরের উত্তরটি দুটি লুপ ব্যবহার করে এবং তাই উন্নত করা যেতে পারে। যেহেতু আমি কোনও এনপিএম মডিউলটি খুঁজে পাইনি যা একটি ও (এন) সমাধান প্রয়োগ করে, আমি নিম্নলিখিতটি তৈরি করেছি (ইউনিট পরীক্ষিত, 100% কোড কভারেজ, মাত্র 0.5 কেবি আকার এবং টাইপগুলি অন্তর্ভুক্ত)। হয়তো এটি কাউকে সহায়তা করে: npmjs.com/package/performant-array-to-tree
ফিলিপ

4
আগ্রহীদের জন্য, কোডটি সহজেই ভ্যানিলা জেএসতে
xec

48

(বোনাস 1: ন্যাডস মাই বা অর্ডার করা যাবে না)

(বোনাস 2: কোনও 3 আরডি পার্টির লাইব্রেরি দরকার নেই, সরল জেএস)

(বোনাস 3: ব্যবহারকারী "এলিয়াস রাবল" বলছেন এটি দ্রুততম সমাধান, নীচে তার উত্তর দেখুন)

এটা এখানে:

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দ্বিতীয়টির ভিতরে নিয়ে যাওয়ার মাধ্যমে?
আরপিএল

@ আরপিএল সম্মত হয়েছে। প্রয়োজনে যে কেউ সহজেই তা পরিবর্তন করতে পারে। অথবা আপনি যদি মনে করেন এটি ডিফল্টভাবে হওয়া উচিত তবে আমি এটি পরিবর্তন করতে পারি।
ফুরকানও

@ ফুরকানও সত্যিই দুর্দান্ত সমাধান, তবে কার্যকরী প্রোগ্রামিং (কোনও রূপান্তর নয়)
ড্যাক ০ ডি ৩

34

একই সমস্যা ছিল, তবে আমি নিশ্চিত হতে পারি না যে ডেটাটি সাজানো হয়েছে কি না । আমি তৃতীয় পক্ষের লাইব্রেরিটি ব্যবহার করতে পারি নি তাই এটি কেবল ভ্যানিলা জেএস; @ স্টিফেনের উদাহরণ থেকে ইনপুট ডেটা নেওয়া যেতে পারে;

 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
সংক্ষিপ্ততম এবং সর্বোত্তম উত্তরটি আমার মনে হয়
java-

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
নোট করুন যে কেবলমাত্র লিঙ্ক-উত্তরগুলি নিরুৎসাহিত করা হয়েছে, এসও উত্তরগুলি সমাধানের সন্ধানের শেষ-পয়েন্ট হওয়া উচিত (বনাম। রেফারেন্সগুলির মধ্যে আরও একটি স্টপওভার, যা সময়ের সাথে সাথে বাসি হয়ে যায়)। লিঙ্কটিকে রেফারেন্স হিসাবে রেখে এখানে একা একা সংক্ষিপ্তসার যুক্ত করার বিষয়টি বিবেচনা করুন
ক্লিওপাত্রা

আমি বুঝতে পারছি না কেন -1, আমি মনে করি এটি একটি ভাল সমাধান তবে দুর্ভাগ্যক্রমে আমি প্যাকেজটি গিটহাব বা অন্য কোনও পাবলিক সারণীতে খুঁজে পাই না
oriaj

প্যাকেজের প্রতি মনোযোগ দেওয়ার জন্য আপনাকে ধন্যবাদ। আমি পরে এটি প্রসারিত করার পরিকল্পনা করছি। সংগ্রহস্থলের লিথটি
DenQ

@রিয়াজ আমি খুশি যে প্রকল্পের উপকার পেয়েছি। কয়েকটি ধারণার পরিকল্পনা
ডেনিউড

সুন্দরভাবে কাজ করে, আপনাকে ধন্যবাদ ডেনিকিউ যদিও এটি আরও পরীক্ষার কভারেজ থাকুক!
ইলিয়াসটি

3

আমি দুটি সর্বাধিক সাধারণ সমাধানগুলির কার্যকারিতা মূল্যায়নের জন্য একটি পরীক্ষার স্ক্রিপ্ট লিখেছি (যার অর্থ ইনপুটটি আগেভাগে সাজানো হয় না এবং কোডটি তৃতীয় পক্ষের লাইব্রেরির উপর নির্ভর করে না), শেখরদত্তু ব্যবহারকারীরা প্রস্তাবিত ( উত্তর দেখুন ) এবং ফুরকানও ( উত্তর দেখুন )।

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

FurkanO এর সমাধানটি দ্রুততম বলে মনে হচ্ছে।

/*
** 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

এটি অর্ডারড আইটেমগুলির জন্য প্রস্তাব is এই ফাংশনটি একটি একক লুপ এবং একটি হ্যাশ টেবিল সহ কাজ করে এবং এর সাথে সমস্ত আইটেম সংগ্রহ করে 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

এটি লোড্যাশজ (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;
	}
}


আমি এই ফাংশনটি অবজেক্টগুলির অ্যারে থেকে গাছের কাঠামোতে রূপান্তর করতে তৈরি করেছি, যা ডি 3 ট্রি ইন্টারেক্টিভ চার্টের জন্য প্রয়োজনীয়। কোডের কেবল 40 টি লাইনের সাথে আমি আউটপুট পেতে সক্ষম হয়েছি। আমি এই ফাংশনটি কার্যকরভাবে লিখেছি জেএসে পুনরাবৃত্তিমূলক ফানশনালিটি ব্যবহার করুন। চেষ্টা করুন এবং আমাকে আপনার প্রতিক্রিয়া জানান। ধন্যবাদ!!!!
কার্তিক রেড্ডি

অ্যাঞ্জারটির জন্য ধন্যবাদ .. এটি আমার ডি 3 ট্রি টপোলজির জন্য পুরোপুরি কাজ করে .. এখন আমার প্রয়োজন আমার নোডের মানগুলির উপর ভিত্তি করে নোডের রঙ পরিবর্তন করা দরকার..এর জন্য আমাকে জেএসএন-তে একটি পতাকা মান পাস করতে হবে । আমি কীভাবে এটি করব .. {"নাম": "শীর্ষ স্তর", "পতাকা": 1, "পিতামাতা": "নাল", "শিশু": [{"নাম": "ভারত", "পতাকা": 0 , "পিতামাতা": "শীর্ষ স্তর", "শিশু": [
পুনেথ কুমার

1

আপনি এনপিএম প্যাকেজ ট্রি-ব্যবহারের দিকে নজর রাখতে পারেন যদি আপনি কোনও এসকিউএল ডিবি ডেটা টেবিল থেকে ডেটা লোড করতে চান তবে এটি খুব সহজও হতে পারে। আপনি সহজেই তৈরি গাছের নোডগুলিতে অতিরিক্ত ডেটা যুক্ত করতে পারেন।

দাবি অস্বীকার, আমি এই প্যাকেজ তৈরি করেছি।


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 },

]);

এর Def ফোল্ডার

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

এখানে স্টিভেন হ্যারিসের একটি পরিবর্তিত সংস্করণ রয়েছে যা সাধারণ ES5 এবং শীর্ষ স্তরের এবং বাচ্চাদের উভয় নোডের অ্যারে ফিরিয়ে দেওয়ার পরিবর্তে আইডিতে কীডযুক্ত একটি বস্তু প্রদান করে।

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

এটি উপরের একটি সংশোধিত সংস্করণ যা একাধিক মূল আইটেমগুলির সাথে কাজ করে, আমি আমার আইডি এবং প্যারেন্টআইডসের জন্য জিইউইডিগুলি ব্যবহার করি যাতে UI এ তাদের তৈরি করে আমি হার্ড কোড রুট আইটেমগুলিকে 0000000-00000-00000-TreeE- রুট-আইটিএম এর মতো

var ট্রি = আনফ্লেটেন (রেকর্ডস, "ট্রি-রুট-আইটিইএম");

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

আপনি এনএমপি প্যাকেজ অ্যারে-টু-ট্রি 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

আমি @ হালসিওন উত্তরের উপর ভিত্তি করে একটি 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

হালনাগাদ

আপনি MapES6 এ প্রবর্তিত অবজেক্টটি ব্যবহার করতে পারেন । মূলত আবার অ্যারেতে ঘুরে বেড়াতে পিতামাতাদের সন্ধান করার পরিবর্তে আপনি ঠিক পিতামাতার আইডিতে অ্যারে থেকে প্যারেন্ট আইটেমটি পেয়ে যাবেন যেমন আপনি সূচী দ্বারা কোনও অ্যারেতে আইটেম পান।

এখানে সহজ উদাহরণ:

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 অনুরোধ করা)। আমি @ শেখার্দতু এর উত্তরটি সত্যিই পছন্দ করেছি , কিন্তু বুঝতে পেরেছিলাম এটি ডেটার মাধ্যমে বহুবার ফিল্টার করতে হয়েছে। আমি ভেবেছিলাম একটি সমাধান হ'ল প্রথমে ডেটা অনুলিপি করে ফুরকানওর উত্তরটি ব্যবহার করা যেতে পারে। আমি আমার সংস্করণটি জেএসপিআইপি-তে চেষ্টা করেছি এবং ফলাফলগুলি যেখানে দুর্ভাগ্যবশত (খুব) দুর্বোধ্য ... এটি মনে হচ্ছে গ্রহণযোগ্য উত্তরটি সত্যিই খুব ভাল! যদিও আমার সংস্করণটি বেশ কনফিগারযোগ্য এবং ব্যর্থ সাফ, তাই আমি যাইহোক এটি আপনার সাথে ভাগ করে নিই; এখানে আমার অবদান:

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
 }

এটি জেসফিডেলে পরীক্ষা করুন


-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;
}, {});

নোড ট্রি থেকে এইচটিএমএল তালিকা তৈরি করুন

আমাদের গাছটি স্থানে থাকা, এখানে এল> এলআই এলিমেন্ট তৈরির জন্য একটি পুনরাবৃত্ত ফাংশন রয়েছে :

/**
 * 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)

আশা করি এটি কাউকে সাহায্য করবে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.