Javascript d3.nest()使用多个相同级别的键嵌套数组元素(创建重复项)
我正在使用泰特收藏的数据,这些数据发布在这里: 我正试图把艺术家按动作分组。艺术家的每个JSON对象都有一个属性“movements”,它是由零个或多个元素组成的数组 例如,Vito Acconci与概念艺术和表演艺术有关:Javascript d3.nest()使用多个相同级别的键嵌套数组元素(创建重复项),javascript,arrays,d3.js,nested,Javascript,Arrays,D3.js,Nested,我正在使用泰特收藏的数据,这些数据发布在这里: 我正试图把艺术家按动作分组。艺术家的每个JSON对象都有一个属性“movements”,它是由零个或多个元素组成的数组 例如,Vito Acconci与概念艺术和表演艺术有关: "movements": [ { "era": { "id": 415, "name": "20th century post-1945", "workCount": 3604 },
"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()。我的问题是,如何处理与多个动作相关的艺术家?我希望它们在每个相关的动作中出现一次
下面是一个JSFIDLE,其中包含数据摘录:如下所示:
我想我实际上需要一个不同于d3.nest()提供的结构,所以这更有意义
可能比需要的复杂一点,但我需要能够通过字符串属性或对象数组重新构造。我使用一个标识符来选择一个对象属性作为数组键。考虑使用贴图,但我正在更改对象,因此关键点不匹配
优化建议仍然受欢迎
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;
};
}
您的数据几乎已经嵌套,这就是问题所在 查看位于的示例(在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;
},{});
这就是我想要的输出:它能被优化吗?也许有一种方法可以用d3.nest()实现,但我还没有听说过。您应该将您的解决方案作为答案发布。谢谢分享:)非常有效的分数,谢谢!我假设原始数据集确实是一组关系表,但他们选择将其公开为艺术家的JSON对象。事实上,这通常是面向公众的web应用程序的用途。存储对象关系并呈现一个漂亮的网站,这样当用户询问某个问题时。但是,如果它输出的是JSON,那么它确实应该以对JSON消费者有意义的方式进行输出,而不是试图通过伪造对象关系来美化数据。