2014-01-24 4 views
0

В моем маленьком приложении, у меня есть функция, возвращающая древовидную данные:Получение списка уникальных элементов из дерева, как объект

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

Данные визуализируются как это:

enter image description here

Адрес jsfiddle.

Я хотел бы создать список меток в правой части основной диаграммы, который будет содержать все значения, которые находятся в листьях дерева, но каждый из них один раз. Другими словами, она должна содержать:

  • "спаржа"
  • "бекон"
  • "бальзамический уксус"
  • и так далее

(как "союз" всех листья)

Как получить этот массив с уникальными элементами?

(Отображение меток не является проблемой для меня когда-то у меня есть этот массив)

Ура!

ответ

1

Таким образом, вы могли бы сделать это очень легко с помощью библиотеки, такой как IxJS, lodash, или underscore.

Однако, здесь вы можете сделать это без внешней зависимости.

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

На данный момент, namesAndCount будет выглядеть примерно так:

{ 
    "fennel":3, 
    "garlic":5, 
    "lemon":9, 
    "onion":5, 
    ... 
} 
+1

Это действительно круто (прилавки)! Благодаря! – VividD

2

Легко восстановить все свойства/атрибуты имен.

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

Для получения уникальных значений массива в JavaScript, пожалуйста, проверьте here.

+0

Нет, это не обхода дочерних узлов. Вы должны ходить по всему дереву. – greim

+0

Узлы - это переменная, которую он использовал в своем скрипте: 'var root = getData(), nodes = radialCluster.nodes (root), ...' Вы видите, что я имею в виду? –

+0

Предполагая, что 'radialCluster.nodes (root)' возвращает сплющенный список, тогда да. – greim

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"] 
1

Вам необходимо выполнить стандартный обход дерева на вашем объекте. Например предположим, у вас есть функция, которая EXECS обратного вызова в каждом узле:

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

Так что я бы сделать:

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

Надежда, что помогает.

Смежные вопросы