【问题标题】:Check two arrays for a JSON property within them检查两个数组中的 JSON 属性
【发布时间】:2016-02-15 15:36:10
【问题描述】:

简介:
我正在使用d3.js 库来绘制强制布局图。为了使图表的更新过程看起来很顺利,我想检查一个名为nodes 的数组,它包含图表中所有当前的nodes 和新的incoming json object(如果它们具有基于name 的共享元素)每个 node 具有的属性。

示例 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 将是一个输入参数功能。

功能:
以下函数会将所有新节点推送到图中。

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() 函数
这个函数应该像过滤器一样工作,并获得nodes 和json.nodes 数组之间的差异。经过多次测试,这是我能想到的最好的。

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 最初将为空。所以我不能像往常一样迭代它。过滤器应该返回所有内容。
  • nodes 和 json.nodes 可能包含相同的数据,因此过滤器不应返回任何内容。
  • json.nodes 拥有 nodes 的所有数据 + 一些额外数据。对于相同的数据应该返回true,对于新的数据应该返回false。
  • json.nodes 的数据少于 nodes,过滤器应返回所有缺失的节点。
  • nodes 和 json.nodes 的数据集完全不同,都应该返回 false。

我在问什么?
我知道这是一项艰巨的任务。我不是要求这里的任何人解决它。我只想知道:

  • 有比使用filter() 更好的选择吗?
  • 我的isInGraph() 是否有明显错误?
  • 在 JavaScript 中是否有同时迭代 2 个数组的好模式?

感谢到目前为止阅读的任何人。如果你觉得我可以改进这个问题,因为它可能写得不太好,或者你(部分)知道如何解决这个问题,请告诉我。

【问题讨论】:

  • “此 JSON 对象将是函数的输入参数” 您展示的函数不接受 JSON。它接受一个对象。如果您正在处理 JavaScript 源代码,并且您不是在处理 string,那么您就不是在处理 JSON。
  • 我正在使用var json = JSON.parse(stringObj); pushNewElements(json);,如果我错了,请纠正我:但这不会使json 成为JSON Object吗?
  • 没有。一旦它被解析,它就只是一个对象,就像任何其他对象一样。 JSON 是一种文本符号。
  • 好的,我改一下,谢谢提示:)

标签: arrays json node.js d3.js filter


【解决方案1】:

你只犯了几个错误,大体思路还可以,我更正/评论了代码:

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

此代码适用于三种明显的情况(nodes 包含 0、1 或 2 个元素)。现在来了lodash one-liner:

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 }
]
*/

【讨论】:

  • 感谢您迄今为止的意见。所以我必须使用lodash 库?在这种情况下它到底做了什么?
  • 你不需要,但有了lodash,你不需要两个函数,你想做的就是在一行代码中完成。在第二段代码中,nodes 中添加了新元素(为了清楚起见,我添加了一个 console.log)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-27
  • 2018-03-05
  • 2022-09-30
  • 2013-08-30
  • 1970-01-01
  • 2018-06-13
  • 2021-09-27
相关资源
最近更新 更多