在javascript数组中查找和修改深层嵌套的对象 [英] find and modify deeply nested object in javascript array

查看:582
本文介绍了在javascript数组中查找和修改深层嵌套的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象数组,可以是任意长度和深度.我需要能够通过其ID查找对象,然后在数组中修改该对象.有没有一种有效的方法可以使用lodash或纯js?

我以为我可以创建一个导致对象的索引数组,但是构造使用这些索引访问对象的表达式似乎过于复杂/不必要

edit1;感谢您的所有答复,我将尝试并更加具体.我目前正在寻找要修改的对象的位置.父对象是目标对象具有的每个父对象的ID数组.对于此数组,祖先可能是个更好的名字. costCenters是包含我要修改的对象的对象数组.此函数递归并返回一个索引数组,该索引导致我要修改的对象

var findAncestorsIdxs = function(parents, costCenters, startingIdx, parentsIdxs) {
            var idx = startingIdx ? startingIdx : 0;
            var pidx = parentsIdxs ? parentsIdxs : [];

            _.each(costCenters, function(cc, ccIdx) {
                if(cc.id === parents[idx]) {
                    console.log(pidx);
                    idx = idx + 1;
                    pidx.push(ccIdx);
                    console.log(pidx);
                    pidx = findAncestorsIdx(parents, costCenters[ccIdx].children, idx, pidx);
                }
            });
            return pidx;
        }; 

现在有了这个索引数组,我如何定位和修改我想要的确切对象?我已经尝试过,其中祖先是索引数组,costCenters是具有要修改的对象的数组,parent是要分配给目标对象的新值

var setParentThroughAncestors = function(ancestors, costCenters, parent) {
            var ccs = costCenters;
            var depth = ancestors.length;
            var ancestor = costCenters[ancestors[0]];
            for(i = 1; i < depth; i++) {
                ancestor = ancestor.children[ancestors[i]];
            }
            ancestor = parent;
            console.log(ccs);
            return ccs;
        };

这显然只是返回未修改的costCenters数组,因此,我可以看到以该对象为目标的唯一另一种方法是构造像myObjects [idx1] .children [2] .grandchildren [3] .ggranchildren [4]之类的表达式.某物= newValue.那是唯一的方法吗?如果是这样的话,最好的方法是什么?

解决方案

正如Felix Kling所说,您可以对所有对象进行递归迭代.

// Overly-complex array
var myArray = {
    keyOne: {},
    keyTwo: {
        myId: {a: '3'}
    }
};
var searchId = 'myId', // Your search key
    foundValue, // Populated with the searched object
    found = false; // Internal flag for iterate()

// Recursive function searching through array
function iterate(haystack) {
    if (typeof haystack !== 'object' || haystack === null) return; // type-safety
    if (typeof haystack[searchId] !== 'undefined') {
        found = true;
        foundValue = haystack[searchId];
        return;
    } else {
        for (var i in haystack) {
            // avoid circular reference infinite loop & skip inherited properties
            if (haystack===haystack[i] || !haystack.hasOwnProperty(i)) continue;

            iterate(haystack[i]);
            if (found === true) return;
        }
    }
}

// USAGE / RESULT
iterate(myArray);
console.log(foundValue); // {a: '3'}
foundValue.b = 4; // Updating foundValue also updates myArray
console.log(myArray.keyTwo.myId); // {a: '3', b: 4}

所有JS对象分配均作为JS中的引用传递.有关对象的完整教程,请参见

感谢@torazaburo提供更好的代码建议.

I have an array of objects that can be of any length and any depth. I need to be able to find an object by its id and then modify that object within the array. Is there an efficient way to do this with either lodash or pure js?

I thought I could create an array of indexes that led to the object but constructing the expression to access the object with these indexes seems overly complex / unnecessary

edit1; thanks for all yours replies I will try and be more specific. i am currently finding the location of the object I am trying to modify like so. parents is an array of ids for each parent the target object has. ancestors might be a better name for this array. costCenters is the array of objects that contains the object I want to modify. this function recurses and returns an array of indexes that lead to the object I want to modify

var findAncestorsIdxs = function(parents, costCenters, startingIdx, parentsIdxs) {
            var idx = startingIdx ? startingIdx : 0;
            var pidx = parentsIdxs ? parentsIdxs : [];

            _.each(costCenters, function(cc, ccIdx) {
                if(cc.id === parents[idx]) {
                    console.log(pidx);
                    idx = idx + 1;
                    pidx.push(ccIdx);
                    console.log(pidx);
                    pidx = findAncestorsIdx(parents, costCenters[ccIdx].children, idx, pidx);
                }
            });
            return pidx;
        }; 

Now with this array of indexes how do I target and modify the exact object I want? I have tried this where ancestors is the array of indexes, costCenters is the array with the object to be modified and parent is the new value to be assigned to the target object

var setParentThroughAncestors = function(ancestors, costCenters, parent) {
            var ccs = costCenters;
            var depth = ancestors.length;
            var ancestor = costCenters[ancestors[0]];
            for(i = 1; i < depth; i++) {
                ancestor = ancestor.children[ancestors[i]];
            }
            ancestor = parent;
            console.log(ccs);
            return ccs;
        };

this is obviously just returning the unmodified costCenters array so the only other way I can see to target that object is to construct the expression like myObjects[idx1].children[2].grandchildren[3].ggranchildren[4].something = newValue. is that the only way? if so what is the best way to do that?

解决方案

As Felix Kling said, you can iterate recursively over all objects.

// Overly-complex array
var myArray = {
    keyOne: {},
    keyTwo: {
        myId: {a: '3'}
    }
};
var searchId = 'myId', // Your search key
    foundValue, // Populated with the searched object
    found = false; // Internal flag for iterate()

// Recursive function searching through array
function iterate(haystack) {
    if (typeof haystack !== 'object' || haystack === null) return; // type-safety
    if (typeof haystack[searchId] !== 'undefined') {
        found = true;
        foundValue = haystack[searchId];
        return;
    } else {
        for (var i in haystack) {
            // avoid circular reference infinite loop & skip inherited properties
            if (haystack===haystack[i] || !haystack.hasOwnProperty(i)) continue;

            iterate(haystack[i]);
            if (found === true) return;
        }
    }
}

// USAGE / RESULT
iterate(myArray);
console.log(foundValue); // {a: '3'}
foundValue.b = 4; // Updating foundValue also updates myArray
console.log(myArray.keyTwo.myId); // {a: '3', b: 4}

All JS object assignations are passed as reference in JS. See this for a complete tutorial on objects :)

Edit: Thanks @torazaburo for suggestions for a better code.

这篇关于在javascript数组中查找和修改深层嵌套的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆