2014-02-11 2 views
0

я работаю с данными из коллекции Тейт опубликованных здесь: https://github.com/tategallery/collectiond3.nest() элементы Nest массива с несколькими ключами же уровня (создание дубликатов)

Я пытаюсь группы художников движением. Каждый объект JSON художника имеет свойство «движений», которое представляет собой массив из нуля или более элементов.

Например, Аккончи связан с концептуальным искусством и перформансом:

"movements": [ 
    { 
     "era": { 
     "id": 415, 
     "name": "20th century post-1945", 
     "workCount": 3604 
     }, 
     "id": 421, 
     "name": "Conceptual Art", 
     "workCount": 478 
    }, 
    { 
     "era": { 
     "id": 415, 
     "name": "20th century post-1945", 
     "workCount": 3604 
     }, 
     "id": 436, 
     "name": "Performance Art", 
     "workCount": 81 
    } 
] 

Теперь я хочу, чтобы группа художников их движения, в идеале используя d3.nest(). Моя проблема в том, как я обрабатываю художников, связанных с несколькими движениями? Я бы хотел, чтобы они появлялись один раз в каждом связанном движении.

Вот JSFiddle выписку из данных: http://jsfiddle.net/jwFZV/

+0

Это результат, который я хочу: http: // jsfiddle.net/fEyZ6/5/ Можно ли оптимизировать? – Florian

+0

Возможно, это способ реализовать это с помощью d3.nest(), но я не слышал об этом. Вы должны отправить свое решение в качестве ответа. Спасибо, что поделились ею :) –

ответ

0

решил его так: http://jsfiddle.net/fEyZ6/6/

Фигурные я на самом деле нужно другую структуру, чем та, представленной d3.nest(), так что этот сделал больше смысла.

Может быть немного сложнее, чем необходимо, но мне нужно было реструктурировать свойство string или массив объектов. Я использую идентификатор, чтобы выбрать свойство объекта в качестве ключа массива. Считается с использованием карты, но я меняю объекты, поэтому ключи не совпадают.

Предложения по оптимизации по-прежнему приветствуются.

var Hierarchy = function(data, accessor) { 

    var data = data, 
     accessor = accessor, 
     identifier = "name", 
     hierarchy = false, 
     rebuild = false; 

    this.hierarchy = function() { 

     if(hierarchy && !rebuild) { 
      return hierarchy; 
     } 

     hierarchy = []; 
     var keys = []; 

     if(!accessor) { 
      console.log("ERROR no accessor for hierarchy"); 
      return false; 
     } 


     for (var i in data) { 

      var parents = accessor.call(data, data[i]); 

      if(Object.prototype.toString.call(parents) != "[object Array]") { 

       parents = [parents]; 

      }; 

      parents.forEach(function(element) { 

       if(typeof element === "object") { 

        p = keys[element[identifier]]; 

       } else { 

        p = keys[element]; 

       } 

       if (!p) { 

        p = { 
         element: element, 
         children: [] 
        }; 
       } 

       p.children.push(data[i]); 


       if(typeof element === "object") { 

        keys[element[identifier]] = p; 

       } else { 

        keys[element] = p; 

       } 

      }) 


     } 

     for (var i in keys) { 

      if(typeof keys[i].element != "object") { 
       keys[i].element = { 
        name: keys[i].element 
       } 
      } 

      keys[i].element.children = keys[i].children; 
      hierarchy.push(keys[i].element); 

     } 

     rebuild = false; 

     return hierarchy; 
    } 

    // accessors 
    this.data = function(_) { 
     if(!arguments.length) return data; 
     data = _; 
     rebuild = true; 
    }; 

    this.identifier = function(_) { 
     if(!arguments.length) return identifier; 
     identifier = _; 
     rebuild = true; 
    }; 

    this.accessor = function(_) { 
     if(!arguments.length) return accessor; 
     accessor = _; 
     rebuild = true; 
    }; 


} 
0

Ваши данные в значительной степени уже вложены, вот в чем проблема.

Посмотрите пример на https://github.com/mbostock/d3/wiki/Arrays#wiki-d3_pairs (после d3.pairs).

Пример начинается с плоского набора данных из трех похожих объектов, и после его вложенности объекты дублируются, чтобы принадлежать нескольким группам одновременно. Это гораздо более универсальный инструмент, чем объект вложенного объекта JSON, поскольку вместо ссылок на объекты вместо него создаются новые.

В вашем наборе данных движения дублируются под несколькими исполнителями, но если у двух художников одинаковое движение, вы не можете сравнивать их с помощью ==. Он всегда будет возвращать false.

Другой подход - отправить каждую коллекцию объектов (художников, движений ...), поскольку это собственный плоский массив объектов. Объекты могут показать свое отношение к другим объектам каким-либо ключевым свойством или списком индексов связанных объектов.

Подход таблицы также позволит вам отправлять ваши данные клиенту в виде CSV или TSV. Если вы имеете дело с огромным набором данных, вы знаете, сколько ключей космического объекта заняло, и они одинаковы для каждого объекта! Заголовок таблицы решает эту проблему. Это становится намного более заметным при работе с целыми числами и короткими строковыми значениями.

Чтобы начать, вы должны избавиться от повторяющихся объектов и выделить разные типы данных. Это даст вам гораздо более чистую отправную точку.

Вот пара пистолетных отрывков для начала. Они работают на

var artists = data; 

var movements = data.reduce(function(object, artist){ 
    artist.movements = artist.movements.map(function(movement){ 
    object[movement.id] = object[movement.id] || movement; 
    return movement.id; 
    }).join(','); 
    return object; 
},{}); 

var eras = d3.values(movements).reduce(function(object, movement){ 
    var eid = movement.era.id; 
    object[eid] = object[eid] || movement.era; 
    movement.era = eid; 
    return object; 
},{}); 
+0

Очень действительные точки, спасибо! Я предполагаю, что исходный набор данных действительно представляет собой набор реляционных таблиц, но они решили разоблачить его как объекты JSON художников. – Florian

+0

Это обычно так, на самом деле, это в значительной степени цель публичного веб-приложения. Чтобы сохранить отношения объектов и сделать красивый веб-сайт, чтобы пользователь спросил его. Однако, если он выводит JSON, тогда он действительно должен делать это таким образом, который имеет смысл для потребителей JSON, а не пытается усложнять данные путем фальсификации отношений объектов. – Julian