简体   繁体   中英

remove leaf nodes from data

I'm making a circle packing and there are too many nodes in the graphic, so I'm trying to reduce the amount of nodes by removing the leaf nodes.

The data I get from the api is a json object that looks like this:


{
    Children: [], 
    Label: "some str", 
    Value: some int, 
    Properties:[]
}

I am trying to make a function that loops through the data and if the object has no children it gets removed. Here is what I'm on

function removeLeaves(data){
let keys = Object.entries(data);
for(let [name,obj] of keys){
    if(name == "Children"){
        if((<Array<any>>obj).length > 0){
            for(let child of (<Array<any>>obj)){

                removeLeaves(child);
            }
        }
        else{
            data = {}; //delete object
        }
    }

  }
}

but since data is not a reference type the changes aren't saved. Can anyone help me with this? I'm trying to do something similar to the c# removeLeaves(ref data)

Or is there a way I can remove the leaves in the pack method

var pack = data => d3.pack()
    .size([width, height])
    .padding(5)
    (d3.hierarchy(data, d => d.Children)
     //here some kind of filtering
    .sum(d => {            
        return d.Value;
    })
    .sort((a, b) => b.value - a.value));

I would choose an approach that recursively/programmatically builds the desired data structure instead of mutating the existing input-data by deleting the not needed properties...

 // {Children: [], Label: "some str", Value: some int, Properties:[] } const data = { Label: "root_with_children", Value: 1, Properties: ["foo", "bar"], Children: [{ Label: "level_1_without_children", Value: 2, Properties: ["foo", "bar"], Children: [] }, { Label: "level_1_with_children", Value: 3, Properties: ["foo", "bar"], Children: [{ Label: "level_2_without_children", Value: 4, Properties: ["foo", "bar"], Children: [] }, { Label: "level_2_with_children", Value: 5, Properties: ["foo", "bar"], Children: [{ Label: "level_3_without_children", Value: 6, Properties: ["foo", "bar"], Children: [] }] }] }] }; function isNonEmtyArray(type) { return (Array.isArray(type) && (type.length >= 1)); } function collectItemsWithChildrenOnly(list, item) { const { Children } = item; if (isNonEmtyArray(Children)) { const copy = Object.assign({}, item, { Children: [] }); list.push(copy); Children.reduce(collectItemsWithChildrenOnly, copy.Children); } return list; } let test; test = [data].reduce(collectItemsWithChildrenOnly, []); console.log('1st run:: test: ', test); test = test.reduce(collectItemsWithChildrenOnly, []); console.log('2nd run:: test: ', test); test = test.reduce(collectItemsWithChildrenOnly, []); console.log('3rd run:: test: ', test); test = test.reduce(collectItemsWithChildrenOnly, []); console.log('4th run:: test: ', test); test = test.reduce(collectItemsWithChildrenOnly, []); console.log('countercheck:: test: ', test);
 .as-console-wrapper { min-height: 100%;important: top; 0; }

asuming you get the array of objects with Children property being an array of object or an empty arr indicating it being a leaf you can remove the leaf nodes with combination of following functions

const removeEmptyChildren = obj => obj.Children.length
?
    {...obj,Children:leafRemover(obj.Children)}
:
    undefined


const leafRemover = arr => arr.filter( e => removeEmptyChildren(e) !== undefined)
console.log(leafRemover(data)) // where data is array of objects from the server

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM