2015-10-01 2 views
2

Я работаю над визуализацией d3, чтобы создать солнечный заряд. Я также добавляю функциональность для поиска определенной дуги, чтобы солнечный свет отображал дуги только с искомой меткой. Если исходный объект:Как фильтровать объект JavaScript на основе состояния свойства?

{ 
    "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); 
      }) 

Это возвращает только «имя»: дугу «В», а не иерархию.

ответ

0

Если вы хотите работать с фильтром .filter(), вам придется сгладить данные вашего JSON, применив фильтр, а затем отключите его. Если вам интересно, вы можете проверить уплощение и размытие. Я лично предпочитаю поиск по глубине (или bfs также работает) и обрезку, где требуется подход. Давайте предположим, ваши данные JSon присутствует в MyData Javascript вар:

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

Теперь ваши ДФС() функция будет выглядеть примерно так:

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

Что происходит здесь является то, что мы делаем depth- первый поиск данных JSON. Первое условие IF проверяет, находится ли мы на уровне листового узла и возвращает false, если свойство «name» имеет значение, отличное от «B». Затем мы пересекаем всех дочерних узлов текущего узла, вызываем dfs() для каждого дочернего элемента и обрезаем его, если он возвращает false. В конце мы возвращаем false, если все дочерние узлы текущего узла были обрезаны, и если свойство «name» текущего узла не является «B» (условие, что нелистовой узел также необходимо обрезать из иерархии). Надеюсь это поможет. Дайте мне знать, если я что-то пропустил.

+0

Я пробовал реализовать это. Спасибо за предложение. Тем не менее, я столкнулся с ошибкой при попытке реализовать то же самое. Ссылка для jsfiddle: http://jsfiddle.net/Claw_22/vw611nx8/2/. При изучении я обнаружил, что вход должен быть в формате массива для функции сращивания. Теперь я смотрю, как я могу сделать это преобразование. – Claw

+0

упс! Эта строка должна быть данными.children.splice (я, 1). Мы пытаемся удалить одного из детей. Дети - это массив, и поэтому сращивание должно работать. Я отредактирую свой ответ, чтобы отразить это изменение. –

+0

Протестировано после изменения. Он работает на моем конце, и иерархия поддерживается после необходимых удалений. Дайте мне знать, если это сработает и для вас. Ура! –

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

+0

Благодарим вас за предоставление альтернативы. Однако я смотрю в основном на подмножество json, чтобы я мог воссоздать солнечный пыль с применением фильтра. У листовых узлов в настоящее время много дубликатов в разных иерархиях. Следовательно, причина. – Claw

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'); }); 
+0

Это действительно элегантное решение. благодаря – Claw

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