0

In my small app, I have a function returning tree-like data:

function getData() {
return {
    "name": "fish",
        "children": [{
        "name": "mussels & clams",
            "children": [{
            "name": "fennel",
                "size": 1
        }, {
            "name": "garlic",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "onion",
                "size": 1
        }, {
            "name": "parsley",
                "size": 1
        }, {
            "name": "pasta",
                "size": 1
        }, {
            "name": "rice",
                "size": 1
        }, {
            "name": "soup",
                "size": 1
        }, {
            "name": "tomato",
                "size": 1
        }]
    }, {
        "name": "octopus",
            "children": [{
            "name": "bay",
                "size": 1
        }, {
            "name": "chilli",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "olive oil",
                "size": 1
        }, {
            "name": "paprika",
                "size": 1
        }, {
            "name": "parsley",
                "size": 1
        }, {
            "name": "pine nuts",
                "size": 1
        }]
    }, {
        "name": "oysters",
            "children": [{
            "name": "asparagus",
                "size": 1
        }, {
            "name": "bacon",
                "size": 1
        }, {
            "name": "butter",
                "size": 1
        }, {
            "name": "cellery",
                "size": 1
        }, {
            "name": "chives",
                "size": 1
        }, {
            "name": "garlic",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "mozzarella",
                "size": 1
        }, {
            "name": "onion",
                "size": 1
        }, {
            "name": "pasta",
                "size": 1
        }, {
            "name": "parsley",
                "size": 1
        }, {
            "name": "shallot",
                "size": 1
        }]
    }, {
        "name": "pink fish",
            "children": [{
            "name": "balsamic vinegar",
                "size": 1
        }, {
            "name": "chives",
                "size": 1
        }, {
            "name": "cream",
                "size": 1
        }, {
            "name": "dill",
                "size": 1
        }, {
            "name": "garlic",
                "size": 1
        }, {
            "name": "ham",
                "size": 1
        }, {
            "name": "honey",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "lime",
                "size": 1
        }, {
            "name": "mild cheese",
                "size": 1
        }, {
            "name": "miso",
                "size": 1
        }, {
            "name": "potato",
                "size": 1
        }, {
            "name": "sesame",
                "size": 1
        }, {
            "name": "soy souce",
                "size": 1
        }, {
            "name": "spinach",
                "size": 1
        }, {
            "name": "thyme",
                "size": 1
        }]
    }, {
        "name": "shrimp",
            "children": [{
            "name": "coriander",
                "size": 1
        }, {
            "name": "curry",
                "size": 1
        }, {
            "name": "ginger",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "lime",
                "size": 1
        }, {
            "name": "lobster",
                "size": 1
        }, {
            "name": "parsley",
                "size": 1
        }, {
            "name": "soft cheese",
                "size": 1
        }, {
            "name": "tomato",
                "size": 1
        }]
    }, {
        "name": "smoked fish",
            "children": [{
            "name": "asparagus",
                "size": 1
        }, {
            "name": "butter",
                "size": 1
        }, {
            "name": "eggs",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "mandarin",
                "size": 1
        }, {
            "name": "mild cheese",
                "size": 1
        }, {
            "name": "mushrooms",
                "size": 1
        }, {
            "name": "onion",
                "size": 1
        }, {
            "name": "potato",
                "size": 1
        }, {
            "name": "spring onion",
                "size": 1
        }]
    }, {
        "name": "squid",
            "children": [{
            "name": "bacon",
                "size": 1
        }, {
            "name": "courgette",
                "size": 1
        }, {
            "name": "cumin",
                "size": 1
        }, {
            "name": "garlic",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "lime",
                "size": 1
        }, {
            "name": "onion",
                "size": 1
        }, {
            "name": "parsley",
                "size": 1
        }, {
            "name": "peper",
                "size": 1
        }, {
            "name": "rocket",
                "size": 1
        }, {
            "name": "thyme",
                "size": 1
        }]
    }, {
        "name": "sushi",
            "children": [{
            "name": "coriander",
                "size": 1
        }, {
            "name": "couscous",
                "size": 1
        }, {
            "name": "cucumber",
                "size": 1
        }, {
            "name": "ginger",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "lime",
                "size": 1
        }, {
            "name": "pepper",
                "size": 1
        }, {
            "name": "rice",
                "size": 1
        }, {
            "name": "sesame",
                "size": 1
        }, {
            "name": "soya souce",
                "size": 1
        }, {
            "name": "spring onion",
                "size": 1
        }, {
            "name": "wasabi",
                "size": 1
        }]
    }, {
        "name": "white fish",
            "children": [{
            "name": "butter",
                "size": 1
        }, {
            "name": "courgette",
                "size": 1
        }, {
            "name": "gream",
                "size": 1
        }, {
            "name": "fennel",
                "size": 1
        }, {
            "name": "french beans",
                "size": 1
        }, {
            "name": "garlic",
                "size": 1
        }, {
            "name": "leak",
                "size": 1
        }, {
            "name": "lemon",
                "size": 1
        }, {
            "name": "lime",
                "size": 1
        }, {
            "name": "mild cheese",
                "size": 1
        }, {
            "name": "onion",
                "size": 1
        }, {
            "name": "parsley",
                "size": 1
        }, {
            "name": "soup",
                "size": 1
        }, {
            "name": "soya souce",
                "size": 1
        }, {
            "name": "tomato",
                "size": 1
        }]
    }, {
        "name": "caviar",
            "children": [{
            "name": "chives",
                "size": 1
        }, {
            "name": "eggs",
                "size": 1
        }, {
            "name": "sour cream",
                "size": 1
        }, {
            "name": "strong cheese",
                "size": 1
        }]
    }, {
        "name": "lobster & crab",
            "children": [{
            "name": "chili",
                "size": 1
        }, {
            "name": "coriander",
                "size": 1
        }, {
            "name": "fennel",
                "size": 1
        }, {
            "name": "ginger",
                "size": 1
        }, {
            "name": "leek",
                "size": 1
        }, {
            "name": "mayonnaise",
                "size": 1
        }, {
            "name": "parsley",
                "size": 1
        }, {
            "name": "pasta",
                "size": 1
        }, {
            "name": "peas",
                "size": 1
        }, {
            "name": "rice",
                "size": 1
        }, {
            "name": "sesame",
                "size": 1
        }, {
            "name": "soy sauce",
                "size": 1
        }, {
            "name": "wasabi",
                "size": 1
        }]
    }]
};}

The data is visualized like this:

enter image description here

Here is jsfiddle.

I would like to create a list of labels on the right hand side of the main diagram, that would contain all values that are found in leaves of the tree, but each one only once. In other words, it should contain:

  • "asparagus"
  • "bacon"
  • "balsamic vinegar"
  • and so on

(like a "union" of all leaves)

How do I get that array with unique elements?

(Displaying labels is not a problem for me once I have that array)

Cheers!

VividD
  • 10,456
  • 6
  • 64
  • 111

4 Answers4

2

It's easy to retreive all the names properties / attributes.

var fishNames = nodes.map(function(x){return x.name});

For getting unique values of an array in javascript, please check here.

Community
  • 1
  • 1
php-dev
  • 6,998
  • 4
  • 24
  • 38
  • No, this doesn't traverse child nodes. You have to walk the entire tree. – greim Jan 24 '14 at 18:37
  • nodes is a variable he used in his script : `var root = getData(), nodes = radialCluster.nodes(root), ...` Do you see what I mean? – php-dev Jan 24 '14 at 18:42
  • Assuming `radialCluster.nodes(root)` returns a flattened list, then yes. – greim Jan 24 '14 at 18:51
1
var data = getData();
var namesObj = {}; // Put leaves into object first for uniqueness
for( var c0 in data.children )
  for( var c1 in data.children[c0].children )
    namesObj[data.children[c0].children[c1].name] = 1;

var names = []; // Then put unique leaves into an array
for( var name in namesObj ) names.push(name);

names // ["fennel", "garlic", "lemon", "onion", "parsley", "pasta", "rice", "soup", "tomato", "bay", "chilli", "olive oil", "paprika", "pine nuts", "asparagus", "bacon", "butter", "cellery", "chives", "mozzarella", "shallot", "balsamic vinegar", "cream", "dill", "ham", "honey", "lime", "mild cheese", "miso", "potato", "sesame", "soy souce", "spinach", "thyme", "coriander", "curry", "ginger", "lobster", "soft cheese", "eggs", "mandarin", "mushrooms", "spring onion", "courgette", "cumin", "peper", "rocket", "couscous", "cucumber", "pepper", "soya souce", "wasabi", "gream", "french beans", "leak", "sour cream", "strong cheese", "chili", "leek", "mayonnaise", "peas", "soy sauce"]
Matt
  • 20,108
  • 1
  • 57
  • 70
1

You need to do a standard tree-traversal on your object. For example suppose you have a function that execs a callback at each node:

walkObject(obj, function(obj, name, parent){
  /* obj === parent[name] */
});

So I'd do:

var names = {};
walkObject(nodes, function(obj, name, parent){
  if (name !== 'name') return;
  names[obj] = true;
});
var uniqueList = Object.keys(names);

Hope that helps.

greim
  • 9,149
  • 6
  • 34
  • 35
1

So you could definitely do this very easily with a library like IxJS, lodash, or underscore.

However, here's one way you could do it without an external dependancy.

function flatMap (arr, selector) {
  return Array.prototype.concat.apply([], arr.map(selector));
}

var names =
  flatMap(getData().children, function (x) { return x.children; })
    .map(function (x) { return x.name; });

var length = names.length;
var namesAndCount = {};

for (var i = 0; i < length; i++) {
  var name = names[i];
  namesAndCount[name] = namesAndCount[name] ? namesAndCount[name] + 1 : 1;
}

At this point, namesAndCount would look similar to this:

{
  "fennel":3,
  "garlic":5,
  "lemon":9,
  "onion":5,
  ...
}
cwharris
  • 17,835
  • 4
  • 44
  • 64