如何根据属性条件过滤JavaScript对象?

时间:2015-10-01 02:59:40

标签: javascript d3.js

我正在研究d3可视化以创建一个sunburst。我还添加了一个搜索特定弧的功能,以便sunburst显示仅包含搜索标签的弧。如果初始对象是:

{
    "name": "root",
    "children": [
        {
            "name": "A",
            "color": "red",
            "children": [
                {
                    "name": "B",
                    "color": "red"
                }
            ]
        },
        {
            "name": "C",
            "color": "red",
            "children": [
                {
                    "name": "D",
                    "color": "red"
                }
            ]
        },
        {
            "name": "E",
            "color": "red",
            "children": [
                {
                    "name": "B",
                    "color": "red"
                }
            ]
        }
    ]
}

我想对此进行过滤,使其返回整个层次结构,其中包含层次结构中任何位置的搜索名称。以下是搜索"名称"所需的示例输出:" B"

{
    "name": "root",
    "children": [
        {
            "name": "A",
            "color": "red",
            "children": [
                {
                    "name": "B",
                    "color": "red"
                }
            ]
        },
        {
            "name": "E",
            "color": "red",
            "children": [
                {
                    "name": "B",
                    "color": "red"
                }
            ]
        }
    ]
}

请告诉我是否还需要其他任何东西。谢谢。

我尝试过滤的代码段。

var path = svg.selectAll("path")
           .data(partition.nodes(root))
           .enter()
           .append("path")
           .filter(function(d){ 
               return (d.name=="B");
           })
           .attr("d", arc)
           .style("fill", function(d) {
               console.log(d.name);
               return color((d.children ? d : d.parent).name); 
           })

这仅返回" name":" B"弧而不是层次结构。

3 个答案:

答案 0 :(得分:0)

如果你想让.filter()方式为你工作,你必须展平你的JSON数据应用一个过滤器,然后取消它。如果您有兴趣,可以查看展平和不展平。 我个人更喜欢深度优先搜索(或bfs也工作)和修剪所需的方法。让我们假设您的json数据存在于mydata javascript var:

d3.json("jsonData.json",function(error,jsonData){
  if(error)
    return console.warn(error);
  var mydata = jsonData;
  dfs(mydata,'B');
});

现在你的dfs()函数看起来像这样:

function dfs(data,label){
  if(!('children' in data))
    return data.name==label;
  for(var i=0;i<data.children.length;++i)
    if(dfs(data.children[i],label)==flase)
      data.children.splice(i--,1);
  return data.children.length > 0 || data.name==label;
}

这里发生的是我们正在深度优先搜索JSON数据。第一个IF条件检查我们是否处于叶节点级别,如果名称&#39;则返回false。财产不是什么,而是&#39; B&#39;接下来,我们遍历当前节点的所有子节点,为每个子节点调用dfs(),如果返回false则修剪该子节点。最后,如果当前节点的所有子节点都已被修剪,并且如果名称为&#39;那么我们将返回false。当前节点的属性不是&#39; B&#39; (必须从层次结构中修剪非叶节点的条件)。希望这可以帮助。如果我错过了什么,请告诉我。

答案 1 :(得分:0)

我的预感是你要在sunburst中为搜索节点及其父节点着色。

为了做到这一点,我创建了一个函数,以递归方式为节点的父颜色着色:

function colorGraph(node){

    var sel = svg.selectAll("path").filter(function (d) {
        return (node==d);
    });
    sel.style("opacity", 1);
    //if parent present change its opacity
    if(node.parent){
        colorGraph(node.parent)
    }
}

完整的工作代码here

答案 2 :(得分:0)

您需要预过滤,而不是在D3管道中进行过滤。

定义一个过滤函数,我们将调用hasName来检查特定对象是否具有所需的名称,或者递归地,如果它的任何子对象具有它:

// Does the object contain a specified name, however many levels down?
function hasName(obj, name) {
  return function _hasName(o) {
    return o.name === name || (o.children || []).some(_hasName);
  }(obj);

}

现在过滤:

data.children = data.children.filter(function(child) { return hasName(child, 'B'); });