एक सपाट संरचना से एक पेड़ का कुशलतापूर्वक निर्माण कैसे करें?


153

मेरे पास एक सपाट संरचना में वस्तुओं का एक गुच्छा है। इन वस्तुओं में IDएक ParentIDसंपत्ति है और इसलिए उन्हें पेड़ों में व्यवस्थित किया जा सकता है। वे किसी क्रम विशेष में नहीं हैं। प्रत्येक ParentIDसंपत्ति जरूरी IDसंरचना में एक के साथ मेल नहीं खाती है । इसलिए इन वस्तुओं से उनके कई पेड़ उभर सकते हैं।

आप परिणामी पेड़ों को बनाने के लिए इन वस्तुओं को कैसे संसाधित करेंगे?

मैं एक समाधान से बहुत दूर नहीं हूँ, लेकिन मुझे यकीन है कि यह इष्टतम से बहुत दूर है ...

मुझे इन पेड़ों को फिर उचित क्रम में एक डेटाबेस में डेटा सम्मिलित करने के लिए बनाने की आवश्यकता है।

कोई परिपत्र संदर्भ नहीं हैं। एक नोड एक रूटनोड है जब ParentID == अशक्त है या जब अन्य वस्तुओं में ParentID नहीं मिल सकता है


"बनाने" से आपका क्या तात्पर्य है? UI में रेंडर? XML या डेटाबेस में एक पदानुक्रमित फैशन में स्टोर करें?
RedFilter

आप किसी अभिभावक (यानी रूट नोड) के साथ एक नोड कैसे परिभाषित करते हैं। पैरेंटआईडी अशक्त है? पेरेंटिड = 0? मुझे लगता है कि कोई परिपत्र संदर्भ सही नहीं हैं?
जेसन Punyon

5
मुझे यह सवाल काफी अच्छा लगता है।
nes1983

1
इस लेख को देखें: scip.be/index.php?Page=ArticlesNET23&Lang=NL
ebram khalil

जवाबों:


120

विशिष्ट वस्तु के लिए एक हैश तालिका मानचित्रण में वस्तुओं की आईडी स्टोर करें। सभी वस्तुओं के माध्यम से प्रवेश करें और अगर यह मौजूद है तो अपने माता-पिता को ढूंढें और तदनुसार अपने माता-पिता के सूचक को अपडेट करें।

class MyObject
{ // The actual object
    public int ParentID { get; set; }
    public int ID { get; set; }
}

class Node
{
    public List<Node> Children = new List<Node>();
    public Node Parent { get; set; }
    public MyObject AssociatedObject { get; set; }
}

IEnumerable<Node> BuildTreeAndGetRoots(List<MyObject> actualObjects)
{
    Dictionary<int, Node> lookup = new Dictionary<int, Node>();
    actualObjects.ForEach(x => lookup.Add(x.ID, new Node { AssociatedObject = x }));
    foreach (var item in lookup.Values) {
        Node proposedParent;
        if (lookup.TryGetValue(item.AssociatedObject.ParentID, out proposedParent)) {
            item.Parent = proposedParent;
            proposedParent.Children.Add(item);
        }
    }
    return lookup.Values.Where(x => x.Parent == null);
}

5
वह कौन सी भाषा है? (मैं इसे सी # लेता हूं)
जेसन एस

3
यह अहंकार (अनौपचारिक संकेतन में) O (3N) है, जहाँ O (1N) समाधान के रूप में गैर 'ट्रैवर्स' माता-पिता के लिए या तो आंशिक नोड्स को तुरंत या तो गैर-तात्कालिक बच्चों के लिए एक माध्यमिक लुक-अप टेबल रखकर आसानी से प्राप्त किया जा सकता है। माता-पिता। ज्यादातर वास्तविक दुनिया के उपयोग के लिए कोई फर्क नहीं पड़ता, लेकिन यह बड़े डेटा सेट पर महत्वपूर्ण हो सकता है।
एंड्रयू हैनॉन

15
@AndrewHanlon शायद आपको 0 (1N) के लिए सोल पोस्ट करना चाहिए
Ced

1
@Ced मार्टिन श्मिट का जवाब नीचे दिया गया है कि मैं इसे कैसे लागू करूंगा। जैसा कि देखा जा सकता है, यह एक लूप का उपयोग करता है और बाकी हैशटेबल ऑपरेशन हैं।
एंड्रयू हनलन

26
O (3N) सिर्फ O (N);) है
JakeWilson801

34

मेहरदाद अफशरी के जवाब और एक गति के लिए एंड्रयू हैनलोन की टिप्पणी के आधार पर, यहाँ मेरा लेना है।

मूल कार्य के लिए महत्वपूर्ण अंतर: एक रूट नोड में आईडी == पेरेंटिड है।

class MyObject
{   // The actual object
    public int ParentID { get; set; }
    public int ID { get; set; }
}

class Node
{
    public List<Node> Children = new List<Node>();
    public Node Parent { get; set; }
    public MyObject Source { get; set; }
}

List<Node> BuildTreeAndGetRoots(List<MyObject> actualObjects)
{
    var lookup = new Dictionary<int, Node>();
    var rootNodes = new List<Node>();

    foreach (var item in actualObjects)
    {
        // add us to lookup
        Node ourNode;
        if (lookup.TryGetValue(item.ID, out ourNode))
        {   // was already found as a parent - register the actual object
            ourNode.Source = item;
        }
        else
        {
            ourNode = new Node() { Source = item };
            lookup.Add(item.ID, ourNode);
        }

        // hook into parent
        if (item.ParentID == item.ID)
        {   // is a root node
            rootNodes.Add(ourNode);
        }
        else
        {   // is a child row - so we have a parent
            Node parentNode;
            if (!lookup.TryGetValue(item.ParentID, out parentNode))
            {   // unknown parent, construct preliminary parent
                parentNode = new Node();
                lookup.Add(item.ParentID, parentNode);
            }
            parentNode.Children.Add(ourNode);
            ourNode.Parent = parentNode;
        }
    }

    return rootNodes;
}

1
अच्छा, यह मूल रूप से वह दृष्टिकोण था जिससे मैं सहमत था। लेकिन मैं बस एक छद्म रूट नोड (आईडी = 0 और अशक्त जनक के साथ) का उपयोग करूंगा और स्व संदर्भ आवश्यकता को हटा दूंगा।
एंड्रयू हैनॉन

इस उदाहरण में केवल एक चीज गायब है जो पेरेंट फ़ील्ड को प्रत्येक बच्चों के नोड में असाइन कर रही है। ऐसा करने के लिए, हमें केवल माता-पिता फ़ील्ड सेट करने की आवश्यकता है, बच्चों को इसके मूल संग्रह में जोड़ने के बाद। जैसे: parentNode.Children.Add (ourNode); ourNode.Parent = parentNode;
प्लायिरोला

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

4
चूँकि मुझे एक npm मॉड्यूल नहीं मिला, जो O (n) समाधान को लागू करता है, मैंने निम्नलिखित एक (इकाई परीक्षण, 100% कोड कवरेज, केवल 0.5 kb आकार में बनाया और टाइपिंग शामिल है। शायद यह किसी की मदद करता है: npmjs.com/package / परफ़ॉर्मेंट-एरे-टू-ट्री
फिलिप स्टैनिस्लास

32

यहाँ एक सरल जावास्क्रिप्ट एल्गोरिथ्म है जो माता-पिता / बच्चे के पेड़ की संरचना में एक फ्लैट टेबल को पार्स करता है जो एन समय में चलता है:

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

var root = {id:0, parent_id: null, children: []};
var node_list = { 0 : root};

for (var i = 0; i < table.length; i++) {
    node_list[table[i].id] = table[i];
    node_list[table[i].parent_id].children.push(node_list[table[i].id]);
}

console.log(root);

इस दृष्टिकोण को C # में बदलने का प्रयास कर रहा है।
हांक

एहसास हुआ कि अगर आईडी 1001 जैसी किसी बड़ी चीज से शुरू होती है, तो हमें सूचकांक को अपवाद से बाहर कर दिया जाता है ...
हांक

2
युक्ति: console.log(JSON.stringify(root, null, 2));आउटपुट को सुंदर प्रिंट करने के लिए उपयोग करें।
aloisdg

14

अजगर का हल

def subtree(node, relationships):
    return {
        v: subtree(v, relationships) 
        for v in [x[0] for x in relationships if x[1] == node]
    }

उदाहरण के लिए:

# (child, parent) pairs where -1 means no parent    
flat_tree = [
     (1, -1),
     (4, 1),
     (10, 4),
     (11, 4),
     (16, 11),
     (17, 11),
     (24, 17),
     (25, 17),
     (5, 1),
     (8, 5),
     (9, 5),
     (7, 9),
     (12, 9),
     (22, 12),
     (23, 12),
     (2, 23),
     (26, 23),
     (27, 23),
     (20, 9),
     (21, 9)
    ]

subtree(-1, flat_tree)

पैदा करता है:

{
    "1": {
        "4": {
            "10": {}, 
            "11": {
                "16": {}, 
                "17": {
                    "24": {}, 
                    "25": {}
                }
            }
        }, 
        "5": {
            "8": {}, 
            "9": {
                "20": {}, 
                "12": {
                    "22": {}, 
                    "23": {
                        "2": {}, 
                        "27": {}, 
                        "26": {}
                    }
                }, 
                "21": {}, 
                "7": {}
            }
        }
    }
}

नमस्ते। मैं आउटपुट में एक और विशेषता कैसे जोड़ूं? अर्थात। नाम, parent_id
साधारण व्यक्ति

अब तक सबसे सुरुचिपूर्ण!
ccpizza

@simpleguy: यदि आप अधिक नियंत्रण की आवश्यकता है, तो सूची की समझ प्रकट की जा सकती है, जैसे:def recurse(id, pages): for row in rows: if row['id'] == id: print(f'''{row['id']}:{row['parent_id']} {row['path']} {row['title']}''') recurse(row['id'], rows)
ccpizza

8

जेएस संस्करण जो एक रूट या जड़ों की एक सरणी लौटाता है, जिसमें से प्रत्येक में संबंधित बच्चों से संबंधित एक चिल्ड्रेन एरे प्रॉपर्टी होगी। आदेशित इनपुट पर निर्भर नहीं करता है, शालीनतापूर्वक कॉम्पैक्ट है, और पुनरावृत्ति का उपयोग नहीं करता है। का आनंद लें!

// creates a tree from a flat set of hierarchically related data
var MiracleGrow = function(treeData, key, parentKey)
{
    var keys = [];
    treeData.map(function(x){
        x.Children = [];
        keys.push(x[key]);
    });
    var roots = treeData.filter(function(x){return keys.indexOf(x[parentKey])==-1});
    var nodes = [];
    roots.map(function(x){nodes.push(x)});
    while(nodes.length > 0)
    {

        var node = nodes.pop();
        var children =  treeData.filter(function(x){return x[parentKey] == node[key]});
        children.map(function(x){
            node.Children.push(x);
            nodes.push(x)
        });
    }
    if (roots.length==1) return roots[0];
    return roots;
}


// demo/test data
var treeData = [

    {id:9, name:'Led Zep', parent:null},
    {id:10, name:'Jimmy', parent:9},
    {id:11, name:'Robert', parent:9},
    {id:12, name:'John', parent:9},

    {id:8, name:'Elec Gtr Strings', parent:5},
    {id:1, name:'Rush', parent:null},
    {id:2, name:'Alex', parent:1},
    {id:3, name:'Geddy', parent:1},
    {id:4, name:'Neil', parent:1},
    {id:5, name:'Gibson Les Paul', parent:2},
    {id:6, name:'Pearl Kit', parent:4},
    {id:7, name:'Rickenbacker', parent:3},

    {id:100, name:'Santa', parent:99},
    {id:101, name:'Elf', parent:100},

];
var root = MiracleGrow(treeData, "id", "parent")
console.log(root)

2
यह सवाल 7 साल पुराना है और पहले से ही मतदान और स्वीकृत जवाब है। यदि आपको लगता है कि आपके पास एक बेहतर समाधान है, तो अपने कोड में कुछ स्पष्टीकरण जोड़ना बहुत अच्छा होगा।
जोडी नेबोट

यह अप्रोच इस प्रकार के डेटा के लिए अच्छी तरह से काम करता है।
कोड़ी सी

4

यहाँ एक भयानक जावास्क्रिप्ट संस्करण मिला: http://oskarhane.com/create-a-nested-array-recursively-in-javascript/

मान लीजिए कि आपके पास एक सरणी है:

const models = [
    {id: 1, title: 'hello', parent: 0},
    {id: 2, title: 'hello', parent: 0},
    {id: 3, title: 'hello', parent: 1},
    {id: 4, title: 'hello', parent: 3},
    {id: 5, title: 'hello', parent: 4},
    {id: 6, title: 'hello', parent: 4},
    {id: 7, title: 'hello', parent: 3},
    {id: 8, title: 'hello', parent: 2}
];

और आप वस्तुओं को इस तरह से घोंसला बनाना चाहते हैं:

const nestedStructure = [
    {
        id: 1, title: 'hello', parent: 0, children: [
            {
                id: 3, title: 'hello', parent: 1, children: [
                    {
                        id: 4, title: 'hello', parent: 3, children: [
                            {id: 5, title: 'hello', parent: 4},
                            {id: 6, title: 'hello', parent: 4}
                        ]
                    },
                    {id: 7, title: 'hello', parent: 3}
                ]
            }
        ]
    },
    {
        id: 2, title: 'hello', parent: 0, children: [
            {id: 8, title: 'hello', parent: 2}
        ]
    }
];

यहां एक पुनरावर्ती फ़ंक्शन है जो इसे बनाता है।

function getNestedChildren(models, parentId) {
    const nestedTreeStructure = [];
    const length = models.length;

    for (let i = 0; i < length; i++) { // for-loop for perf reasons, huge difference in ie11
        const model = models[i];

        if (model.parent == parentId) {
            const children = getNestedChildren(models, model.id);

            if (children.length > 0) {
                model.children = children;
            }

            nestedTreeStructure.push(model);
        }
    }

    return nestedTreeStructure;
}

usuage:

const models = [
    {id: 1, title: 'hello', parent: 0},
    {id: 2, title: 'hello', parent: 0},
    {id: 3, title: 'hello', parent: 1},
    {id: 4, title: 'hello', parent: 3},
    {id: 5, title: 'hello', parent: 4},
    {id: 6, title: 'hello', parent: 4},
    {id: 7, title: 'hello', parent: 3},
    {id: 8, title: 'hello', parent: 2}
];
const nestedStructure = getNestedChildren(models, 0);

हर माता-पिता के लिए यह पूरा मॉडल लूपिंग है - क्या यह O (N ^ 2) नहीं है?
एड रैंडल

4

यूजीन के समाधान के सी # संस्करण में रुचि रखने वाले किसी के लिए, ध्यान दें कि नोड_लिस्ट एक मानचित्र के रूप में एक्सेस किया गया है, इसलिए इसके बजाय एक शब्दकोश का उपयोग करें।

ध्यान रखें कि यह समाधान केवल तभी काम करता है जब तालिका parent_id द्वारा क्रमबद्ध हो ।

var table = new[]
{
    new Node { parent_id = 0, id = 1 },
    new Node { parent_id = 0, id = 2 },
    new Node { parent_id = 0, id = 3 },
    new Node { parent_id = 1, id = 4 },
    new Node { parent_id = 1, id = 5 },
    new Node { parent_id = 1, id = 6 },
    new Node { parent_id = 2, id = 7 },
    new Node { parent_id = 7, id = 8 },
    new Node { parent_id = 8, id = 9 },
    new Node { parent_id = 3, id = 10 },
};

var root = new Node { id = 0 };
var node_list = new Dictionary<int, Node>{
    { 0, root }
};

foreach (var item in table)
{
    node_list.Add(item.id, item);
    node_list[item.parent_id].children.Add(node_list[item.id]);
}

नोड को निम्नानुसार परिभाषित किया गया है।

class Node
{
    public int id { get; set; }
    public int parent_id { get; set; }
    public List<Node> children = new List<Node>();
}

1
यह बहुत पुराना है, लेकिन सूची आइटम 8 को पूरा करने से new Node { parent_id = 7, id = 9 },रोकता node_list.Add(item.id, item);है क्योंकि कुंजी दोहरा नहीं सकती है; यह एक टाइपो है; इसलिए, id = 9 के बजाय , id = 8
Marcelo Scofano

फिक्स्ड। धन्यवाद @MarceloScofano!
जोएल मालोन

3

मैंने C # शिथिलता के आधार पर @ मेहरदाद अफश्री उत्तर में एक सामान्य समाधान लिखा:

void Example(List<MyObject> actualObjects)
{
  List<TreeNode<MyObject>> treeRoots = actualObjects.BuildTree(obj => obj.ID, obj => obj.ParentID, -1);
}

public class TreeNode<T>
{
  public TreeNode(T value)
  {
    Value = value;
    Children = new List<TreeNode<T>>();
  }

  public T Value { get; private set; }
  public List<TreeNode<T>> Children { get; private set; }
}

public static class TreeExtensions
{
  public static List<TreeNode<TValue>> BuildTree<TKey, TValue>(this IEnumerable<TValue> objects, Func<TValue, TKey> keySelector, Func<TValue, TKey> parentKeySelector, TKey defaultKey = default(TKey))
  {
    var roots = new List<TreeNode<TValue>>();
    var allNodes = objects.Select(overrideValue => new TreeNode<TValue>(overrideValue)).ToArray();
    var nodesByRowId = allNodes.ToDictionary(node => keySelector(node.Value));

    foreach (var currentNode in allNodes)
    {
      TKey parentKey = parentKeySelector(currentNode.Value);
      if (Equals(parentKey, defaultKey))
      {
        roots.Add(currentNode);
      }
      else
      {
        nodesByRowId[parentKey].Children.Add(currentNode);
      }
    }

    return roots;
  }
}

नीचे मतदाता, कृपया टिप्पणी करें। मुझे यह जानकर खुशी होगी कि मैंने क्या गलत किया।
HuBeZa

2

यहाँ मेहरद अफश्री द्वारा उत्तर का जावा समाधान है।

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class Tree {

    Iterator<Node> buildTreeAndGetRoots(List<MyObject> actualObjects) {
        Map<Integer, Node> lookup = new HashMap<>();
        actualObjects.forEach(x -> lookup.put(x.id, new Node(x)));
        //foreach (var item in lookup.Values)
        lookup.values().forEach(item ->
                {
                    Node proposedParent;
                    if (lookup.containsKey(item.associatedObject.parentId)) {
                        proposedParent = lookup.get(item.associatedObject.parentId);
                        item.parent = proposedParent;
                        proposedParent.children.add(item);
                    }
                }
        );
        //return lookup.values.Where(x =>x.Parent ==null);
        return lookup.values().stream().filter(x -> x.parent == null).iterator();
    }

}

class MyObject { // The actual object
    public int parentId;
    public int id;
}

class Node {
    public List<Node> children = new ArrayList<Node>();
    public Node parent;
    public MyObject associatedObject;

    public Node(MyObject associatedObject) {
        this.associatedObject = associatedObject;
    }
}

आपको थोड़ा समझाना चाहिए कि कोड के पीछे आपका क्या विचार है।
ज़ियाद अक्की

यह पहले के उत्तर का केवल जावा अनुवाद है
विमल भट्ट

1

अस्पष्ट जैसा कि प्रश्न मुझे लगता है, मैं शायद आईडी से वास्तविक वस्तु के लिए एक नक्शा बनाऊंगा। छद्म जावा में (मैंने जांच नहीं की कि यह काम करता है / संकलन करता है), यह कुछ इस तरह हो सकता है:

Map<ID, FlatObject> flatObjectMap = new HashMap<ID, FlatObject>();

for (FlatObject object: flatStructure) {
    flatObjectMap.put(object.ID, object);
}

और प्रत्येक माता-पिता को देखने के लिए:

private FlatObject getParent(FlatObject object) {
    getRealObject(object.ParentID);
}

private FlatObject getRealObject(ID objectID) {
    flatObjectMap.get(objectID);
}

getRealObject(ID)ऑब्जेक्ट्स (या उनकी आईडी) के संग्रह से ऑब्जेक्ट का पुन: उपयोग और नक्शा करके , आपको एक माता-पिता-> बच्चों का नक्शा भी मिलता है।


1

मैं कोड और O (n लॉग एन) समय की 4 पंक्तियों में ऐसा कर सकता हूं, यह मानते हुए कि शब्दकोश कुछ ट्रीपार्ट जैसा है।

dict := Dictionary new.
ary do: [:each | dict at: each id put: each].
ary do: [:each | (dict at: each parent) addChild: each].
root := dict at: nil.

संपादित करें : ठीक है, और अब मैंने पढ़ा है कि कुछ पेरेंटआईडी नकली हैं, इसलिए उपरोक्त भूल जाओ, और यह करो:

dict := Dictionary new.
dict at: nil put: OrderedCollection new.
ary do: [:each | dict at: each id put: each].
ary do: [:each | 
    (dict at: each parent ifAbsent: [dict at: nil]) 
          add: each].
roots := dict at: nil.

1

अधिकांश उत्तर यह मान लेते हैं कि आप डेटाबेस के बाहर ऐसा करना चाह रहे हैं। यदि आपके पेड़ प्रकृति में अपेक्षाकृत स्थिर हैं और आपको बस किसी तरह पेड़ों को डेटाबेस में मैप करने की आवश्यकता है, तो आप डेटाबेस साइड पर नेस्टेड सेट अभ्यावेदन का उपयोग करने पर विचार कर सकते हैं। जो सेल्को द्वारा पुस्तकों की जाँच करें (या यहाँ सेल्को द्वारा अवलोकन के लिए)।

यदि ओरेकल को किसी भी तरह से बांधा जाता है, तो सीधे SQL दृष्टिकोण के लिए उनके कनेक्ट बाय को देखें।

या तो दृष्टिकोण के साथ, आप डेटाबेस में डेटा लोड करने से पहले पेड़ों को मैप करना पूरी तरह से छोड़ सकते हैं। बस मैंने सोचा कि मैं इसे एक विकल्प के रूप में पेश करूंगा, यह आपकी विशिष्ट आवश्यकताओं के लिए पूरी तरह से अनुचित हो सकता है। मूल प्रश्न का संपूर्ण "उचित क्रम" भाग का तात्पर्य है कि आपको किसी कारण से db में "सही" होने के लिए आदेश की आवश्यकता है? यह मुझे वहाँ के पेड़ों को भी संभालने की ओर धकेल सकता है।


1

यह बिल्कुल वैसा ही नहीं है जैसा कि पूछने वाले ने देखा था, लेकिन मुझे यहां प्रदान किए गए अस्पष्ट जवाब वाले उत्तर के चारों ओर अपना सिर लपेटने में कठिनाई हुई, और मुझे अभी भी लगता है कि यह उत्तर शीर्षक के तहत फिट बैठता है।

मेरा उत्तर एक सीधे-पर-ऑब्जेक्ट के पेड़ पर एक फ्लैट संरचना को मैप करने के लिए है जहां आपके पास ParentIDप्रत्येक वस्तु पर एक है। ParentIDहै nullया 0अगर यह एक जड़ है। पूछने वाले के विपरीत, मैं ParentIDसूची में किसी और चीज के लिए सभी वैध बिंदु मानता हूं :

var rootNodes = new List<DTIntranetMenuItem>();
var dictIntranetMenuItems = new Dictionary<long, DTIntranetMenuItem>();

//Convert the flat database items to the DTO's,
//that has a list of children instead of a ParentID.
foreach (var efIntranetMenuItem in flatIntranetMenuItems) //List<tblIntranetMenuItem>
{
    //Automapper (nuget)
    DTIntranetMenuItem intranetMenuItem =
                                   Mapper.Map<DTIntranetMenuItem>(efIntranetMenuItem);
    intranetMenuItem.Children = new List<DTIntranetMenuItem>();
    dictIntranetMenuItems.Add(efIntranetMenuItem.ID, intranetMenuItem);
}

foreach (var efIntranetMenuItem in flatIntranetMenuItems)
{
    //Getting the equivalent object of the converted ones
    DTIntranetMenuItem intranetMenuItem = dictIntranetMenuItems[efIntranetMenuItem.ID];

    if (efIntranetMenuItem.ParentID == null || efIntranetMenuItem.ParentID <= 0)
    {
        rootNodes.Add(intranetMenuItem);
    }
    else
    {
        var parent = dictIntranetMenuItems[efIntranetMenuItem.ParentID.Value];
        parent.Children.Add(intranetMenuItem);
        //intranetMenuItem.Parent = parent;
    }
}
return rootNodes;

1

यहाँ एक रूबी कार्यान्वयन है:

यह विशेषता नाम या विधि कॉल के परिणाम से कैटलॉग करेगा।

CatalogGenerator = ->(depth) do
  if depth != 0
    ->(hash, key) do
      hash[key] = Hash.new(&CatalogGenerator[depth - 1])
    end
  else
    ->(hash, key) do
      hash[key] = []
    end
  end
end

def catalog(collection, root_name: :root, by:)
  method_names = [*by]
  log = Hash.new(&CatalogGenerator[method_names.length])
  tree = collection.each_with_object(log) do |item, catalog|
    path = method_names.map { |method_name| item.public_send(method_name)}.unshift(root_name.to_sym)
  catalog.dig(*path) << item
  end
  tree.with_indifferent_access
end

 students = [#<Student:0x007f891d0b4818 id: 33999, status: "on_hold", tenant_id: 95>,
 #<Student:0x007f891d0b4570 id: 7635, status: "on_hold", tenant_id: 6>,
 #<Student:0x007f891d0b42c8 id: 37220, status: "on_hold", tenant_id: 6>,
 #<Student:0x007f891d0b4020 id: 3444, status: "ready_for_match", tenant_id: 15>,
 #<Student:0x007f8931d5ab58 id: 25166, status: "in_partnership", tenant_id: 10>]

catalog students, by: [:tenant_id, :status]

# this would out put the following
{"root"=>
  {95=>
    {"on_hold"=>
      [#<Student:0x007f891d0b4818
        id: 33999,
        status: "on_hold",
        tenant_id: 95>]},
   6=>
    {"on_hold"=>
      [#<Student:0x007f891d0b4570 id: 7635, status: "on_hold", tenant_id: 6>,
       #<Student:0x007f891d0b42c8
        id: 37220,
        status: "on_hold",
        tenant_id: 6>]},
   15=>
    {"ready_for_match"=>
      [#<Student:0x007f891d0b4020
        id: 3444,
        status: "ready_for_match",
        tenant_id: 15>]},
   10=>
    {"in_partnership"=>
      [#<Student:0x007f8931d5ab58
        id: 25166,
        status: "in_partnership",
        tenant_id: 10>]}}}

1

स्वीकृत उत्तर मुझे बहुत जटिल लगता है इसलिए मैं इसमें एक रूबी और NodeJS संस्करण जोड़ रहा हूँ

मान लें कि फ्लैट नोड सूची में निम्नलिखित संरचना है:

nodes = [
  { id: 7, parent_id: 1 },
  ...
] # ruby

nodes = [
  { id: 7, parentId: 1 },
  ...
] # nodeJS

फ़्लैट लिस्ट संरचना को एक पेड़ में ऊपर करने वाले फ़ंक्शंस निम्न तरीके से दिखेंगे

रूबी के लिए:

def to_tree(nodes)

  nodes.each do |node|

    parent = nodes.find { |another| another[:id] == node[:parent_id] }
    next unless parent

    node[:parent] = parent
    parent[:children] ||= []
    parent[:children] << node

  end

  nodes.select { |node| node[:parent].nil? }

end

NodeJS के लिए:

const toTree = (nodes) => {

  nodes.forEach((node) => {

    const parent = nodes.find((another) => another.id == node.parentId)
    if(parent == null) return;

    node.parent = parent;
    parent.children = parent.children || [];
    parent.children = parent.children.concat(node);

  });

  return nodes.filter((node) => node.parent == null)

};

मेरा मानना ​​है कि चेक की nullजरूरत हैundefined
उलौरी

@Ullauri NodeJS null == undefined => trueमें
Hirurg103

1

ऐसा करने का एक सुंदर तरीका यह है कि सूची में वस्तुओं को माता-पिता की एक अलग-अलग सूची पकड़े स्ट्रिंग के रूप में दर्शाया जाए, और अंत में एक मूल्य:

server.port=90
server.hostname=localhost
client.serverport=90
client.database.port=1234
client.database.host=localhost

एक पेड़ को इकट्ठा करते समय, आप कुछ इस तरह से समाप्त होते हैं:

server:
  port: 90
  hostname: localhost
client:
  serverport=1234
  database:
    port: 1234
    host: localhost

मेरे पास एक कॉन्फ़िगरेशन लाइब्रेरी है जो कमांड लाइन के तर्कों (सूची) से इस ओवरराइड कॉन्फ़िगरेशन (ट्री) को लागू करती है। एक पेड़ में सूची में एक आइटम जोड़ने के लिए एल्गोरिथ्म यहां है


0

क्या आप केवल उन विशेषताओं का उपयोग करके अटक गए हैं? यदि नहीं, तो बाल नोड्स की एक सरणी बनाना अच्छा हो सकता है, जहाँ आप इन सभी वस्तुओं के माध्यम से एक बार ऐसी विशेषताओं का निर्माण कर सकते हैं। वहां से, बच्चों के साथ नोड का चयन करें लेकिन कोई भी माता-पिता और iteratively आपके पेड़ को ऊपर से नीचे नहीं बनाते हैं।


0

जावा संस्करण

// node
@Data
public class Node {
    private Long id;
    private Long parentId;
    private String name;
    private List<Node> children = new ArrayList<>();
}

// flat list to tree
List<Node> nodes = new ArrayList();// load nodes from db or network
Map<Long, Node> nodeMap = new HashMap();
nodes.forEach(node -> {
  if (!nodeMap.containsKey(node.getId)) nodeMap.put(node.getId, node);
  if (nodeMap.containsKey(node.getParentId)) {
    Node parent = nodeMap.get(node.getParentId);
    node.setParentId(parent.getId());
    parent.getChildren().add(node);
  }
});

// tree node
List<Node> treeNode = nodeMap .values().stream().filter(n -> n.getParentId() == null).collect(Collectors.toList());
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.