简体   繁体   English

Javascript:用 object 填充稀疏数组的简洁方法

[英]Javascript: Concise way to fill sparse array with object

I am using an array to store objects (directed edges between nodes) and would like to use the an array to store the objects such that I can use the index of the array to refer to the object id.我正在使用一个数组来存储对象(节点之间的有向边),并且想使用一个数组来存储对象,这样我就可以使用数组的索引来引用 object id。

 /**
 * Take a graph where 
 * @param {number} N: The number of Nodes of in the graph
 * @param {number[][]} trust: an array of directed edges trust [[a,b]] draws 'a trusts b'
 * @return {number} 
 */
var findJudge = function(N, trust) {
    let nodes = [
        {
            trusts: {},
            trustedBy: {}
        }
    ]    

    trust.forEach(pair => {
        nodes[pair[0]].trusts = pair[1]
        nodes[pair[1]].trusted = pair[0]
    })    
    return -1
};

Sample input: N = 2 and trust = [[1,2]] errors because nodes[2] doesn't exist yet at runtime.示例输入: N = 2trust = [[1,2]]错误,因为nodes[2]在运行时还不存在。

I would like to avoid pre-filling the array with null values if possible in the event that N is a really large number.如果可能的话,我想避免用 null 值预先填充数组,以防 N 是一个非常大的数字。 Perhaps this is not the proper data structure for filling sparse adjacency lists.也许这不是填充稀疏邻接表的正确数据结构。 Is there a way to say var x = new Array(of type object, of length N) ?有没有办法说var x = new Array(of type object, of length N)

Im open to any and all solutions.我对任何和所有解决方案持开放态度。

Edit to show context of problem https://leetcode.com/problems/find-the-town-judge/description/编辑以显示问题https://leetcode.com/problems/find-the-town-judge/description/的上下文

I would like to avoid pre-filling the array with null values if possible in the event that N is a really large number.如果可能的话,我想避免用 null 值预先填充数组,以防 N 是一个非常大的数字。

You can avoid such extreme case by first checking the size of the trust argument.您可以通过首先检查trust参数的大小来避免这种极端情况。 If there is a solution, then at least trust.length >= N-1 .如果有解决方案,那么至少trust.length >= N-1

If however that test passes, then you will anyway need to look at all entries of trust to determine whether there is a judge, and who it is.但是,如果该测试通过,那么您无论如何都需要查看所有trust条目,以确定是否有法官,以及法官是谁。 So then it does not increase the time complexity of the work if you also create all N nodes, before even iterating over trust .因此,如果您还创建所有 N 个节点,甚至在迭代trust之前,它不会增加工作的时间复杂度。

Secondly, your code would currently overwrite information, so that you can only store one trusted person and one trusted-by person per node.其次,您的代码当前会覆盖信息,因此每个节点只能存储一个受信任的人和一个受信任的人。 What you really need is that trusted and trustedBy can store multiple entries;您真正需要的是trustedtrustedBy可以存储多个条目; at least when you want to make a double-threaded graph.至少当你想制作一个双线程图时。

But when you really think about it, you would have enough information if you would only know the count of trusted and the count of trustedBy a node has.但是当你真正考虑它时,如果你只知道一个节点的trusted数量trustedBy数量,你就会得到足够的信息。 The judge must be the one for which the trusted count is zero and the trustedBy count is N-1.法官必须是trusted计数为零且trustedBy计数为N-1 的人。 There cannot be two of those, as that would be a contradiction.不可能有两个,因为那将是一个矛盾。

So, you can avoid creating the graph.因此,您可以避免创建图表。 It is enough that you just store counts, that start with 0.只存储从 0 开始的计数就足够了。

As in JavaScript array indices start with zero and not 1, your nodes array would be indexed by one less than the actual person-id that is used in the trust array.就像在 JavaScript 数组索引从零开始而不是 1 一样,您的nodes数组的索引将比trust数组中使用的实际人员 ID 小一。

Here is how that code could look:以下是该代码的外观:

 var findJudge = function(N, trust) { // Quick exit, to avoid unnecessary looping if (trust.length < N - 1) return -1; // Create all nodes (with index one less -- starting at 0) let nodes = Array.from({ length: N }, () => ({ trusts: 0, trustedBy: 0 })); // Count trust relationships in both directions trust.forEach(([trustedBy, trusted]) => { nodes[trustedBy - 1].trusts++; nodes[trusted - 1].trustedBy++; }); // The only judge meets the following requirements // Add one to the found judge to go from 0-based to 1-based. return nodes.findIndex(node => node.trusts == 0 && node.trustedBy == N - 1) + 1 || -1; }; console.log(findJudge(3, [[1,2],[3,2],[1,3]]));

If you care about speed, then replace all loops with old-style for loops, and instead of the array of objects ( trust ), use two simple arrays of counts ( trusts and trustedBy ), as arrays of integers usually lead to better execution times than arrays of objects.如果您关心速度,则将所有循环替换为旧式for循环,而不是对象数组 ( trust ),使用两个简单的计数 arrays ( truststrustedBy ),因为 arrays 整数通常会导致更好的执行时间比 arrays 的对象。

as per @Bergi suggestion I simply check if object exists or not and create it.根据@Bergi 的建议,我只需检查 object 是否存在并创建它。 Still curious to other suggestions if anyone has any other javascript wizardry如果有人有任何其他 javascript 魔法,仍然对其他建议感到好奇

var findJudge = function(N, trust) {
    function node() {
        trusts: {}
        trustedBy: {}
    }
    let nodes = []

    trust.forEach(pair => {
        pair.forEach(element => {
            if (nodes[element] === undefined)
                nodes[element] = new node()
        })
        nodes[pair[0]].trusts = pair[1]
        nodes[pair[1]].trusted = pair[0]
    })    
    return -1
};

Would have posted this as a comment however comments don't allow for code block formatting.会将此作为评论发布,但评论不允许代码块格式化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM