检查两个数组中的JSON属性
介绍:
我正在使用d3.js
库来绘制一个力布局图。 为了让图的更新过程看起来很平常,我想检查一个名为nodes
的数组,它包含图中的所有当前nodes
和新的incoming json object
如果它们具有基于每个node
具有的name
属性的共享元素)。
示例JSON:
{ "nodes":[ {"name":"Harry Potter", "shortname":"Harry", "id":0}, {"name":"Severus Snape", "shortname":"Severus", "id":1} ], "links":[ {"source":0,"target":1,"relation":"hasTeacher"} ] }
每个name
都是唯一的( 是的,我知道你们中的一些人会争论名字不应该是唯一的原因 ),这个object
将是一个函数的input参数。
function:
以下function将所有新的节点推到图上。
function pushNewElements(json) { var len = json.nodes.length; var difference = json.nodes.filter(function (el) { return isInGraph(el, len); }); difference.forEach(function (node) { nodes.push(node); }); }
filter()
函数
这个函数应该像filter一样工作,并获得nodes
和json.nodes
数组之间的json.nodes
。 经过多次testing,这是我能想到的最好的。
function isInGraph(jnode, arrayLength) { //runs vor each entry in json.nodes, 1 of these objects is jnode for (var i = 0; i < nodes.length + arrayLength; i++) { //nodes.length will return 0 at the beginning, //since no object is in the graph yet, the function won't run enough time. try { //We have to try this, because nodes[i] might be out of bound if (jnode.name == nodes[i].name) { return true; } else { return false; } } catch (err) { java.alert(err.message); return false; } } }
java.alert()
是一个在java控制台上打印的自定义函数。
已知的问题:
-
nodes
最初将是空的。 所以我不能像往常一样迭代它。 filter应该返回一切。 -
nodes
和json.nodes
可以包含相同的数据,因此filter不会返回任何内容。 -
json.nodes
具有nodes
所有数据+一些额外的数据。 对于相同的数据应该返回true,为新的数据false。 -
json.nodes
比nodes
数据less,filter应该返回所有缺less的节点。 -
nodes
和json.nodes
有一个完全不同的数据集,都应该返回false。
我在问什么?
我知道这是一个很大的任务。 我不是在这里要求任何人解决这个问题。 我只是想知道:
- 有没有比使用
filter()
更好的select? - 我在我的
isInGraph()
犯了一个明显的错误吗? - 有没有一个好的模式来同时在JavaScript中迭代2个数组?
感谢迄今为止读过的任何人。 如果你觉得我可以改进这个问题,因为它可能不是很好写,或者你(部分)知道如何解决这个问题,请让我知道。
你只犯了很less的错误,总的想法是好的,我纠正/评论的代码:
var input = { "nodes": [ { "name": "Harry Potter", "shortname": "Harry", "id": 0 }, { "name": "Severus Snape", "shortname": "Severus", "id": 1 } ], "links": [ { "source": 0, "target": 1, "relation": "hasTeacher" } ] }; var nodes = [ // { "name": "Harry Potter", "shortname": "Harry", "id": 0 }, { "name": "Severus Snape", "shortname": "Severus", "id": 1 } ]; function pushNewElements(json) { // you don't need this // var len = json.nodes.length; var difference = json.nodes.filter(function (el) { return !isInGraph(el); // << you want the nodes that are NOT in nodes }); difference.forEach(function (node) { nodes.push(node); }); } function isInGraph(jnode) { for (var i = 0; i < nodes.length; i++) { // if the names match, return true now if (jnode.name == nodes[i].name) { return true; } } // no match found (works with nodes.length == 0) return false; } pushNewElements(input); console.log(nodes);
这段代码适用于三种明显的情况(元素为0,1或2的nodes
)。 现在这里来了lodash单行:
var _ = require('lodash'); var input = { "nodes": [ { "name": "Harry Potter", "shortname": "Harry", "id": 0 }, { "name": "Severus Snape", "shortname": "Severus", "id": 1 } ], "links": [ { "source": 0, "target": 1, "relation": "hasTeacher" } ] }; var nodes = [ // { "name": "Harry Potter", "shortname": "Harry", "id": 0 }, { "name": "Severus Snape", "shortname": "Severus", "id": 1 } ]; // unionBy returns unique values from two arrays, elements are compared by 'name' nodes = _.unionBy(nodes, json.nodes, 'name'); console.log(nodes); /* output: [ { "name": "Severus Snape", "shortname": "Severus", "id": 1 }, { "name": "Harry Potter", "shortname": "Harry", "id": 0 } ] */