对象数组中的递归循环

时间:2016-03-19 13:13:00

标签: javascript arrays recursion

我正在使用可能看起来像这样的结构:

  var data =  {
        "name": "McLaren",
        "drivers": [{
            "name": "BMW",
            "drivers": [{
                "name": "Subaru",
                "drivers": [{
                    "name": "Saab",
                    "drivers": [{
                        "name": "Lexus",
                        "drivers": []
                    }, {
                        "name": "Honda",
                        "drivers": []
                    }]
                }]
            }]
        }]
    }

它的对象包含namedrivers数组。 drivers可以为空,但始终存在。

现在假设我有以下对象:

{
"name": "KIA", 
"drivers":[]
}

我需要将此物体放在正确的位置。在我的帮助下,我得到了以下内容:

McLaren/BMW/Subaru/saab

因此,新对象应该被推送到与雷克萨斯和本田相同的阵列。

我一直在努力想弄清楚如何去做。我一直在想以下几行:

我将路径转换为数组:

var pathArr = ["McLaren","BMW","Subaru","saab"]

尝试使用递归函数:

myFunction(newObject){

        for (var i = 0; i < pathArr.length; i++) {
          recursiveFunc(data.drivers, pathArr[i] )
        }

        var recursiveFunc(driversArr, name) {
          for (var ix = 0; ix < driversArr.length; ix++) {
            if (driversArr[ix].name === name) {        
                recursiveFunc(driversArr[ix].drivers, "HERE I NEED pathArr[1]")

            }
          }
        } 
      }

我觉得我很近,但有些东西丢失了。 我是否可能以错误的方式考虑递归或使其过于复杂? 帮助表示感谢,谢谢!

编辑:

McLaren/BMW/Subaru/saab表示新对象(KIA)应该到达的路径。因此,KIA应该放在名为drivers的对象的saab - arr中。

recursiveFunc()     检查路径名存在于哪个数组中,然后尝试使用此对象数组深入到对象中以查找路径的最后部分(在本例中为saab)。应将新对象推送到此数组。

3 个答案:

答案 0 :(得分:1)

您可以运行此代码,将currentNode根对象传递为var insert = function(currentNode, nodeToInsert, pathArr) { if(pathArr.length == 0) { currentNode.drivers.push(nodeToInsert); return true; } for(var i = 0; i < currentNode.drivers.length; i++) if(currentNode.drivers[i].name == pathArr[0]) return insert(currentNode.drivers[i], nodeToInsert, pathArr.splice(1)); return false; }

Saab

请注意,在您的示例中,您在JSON中有saab,在路径中有{{1}},这将导致路径搜索失败。

答案 1 :(得分:1)

这是一个支持的想法:当数据难以处理时,转换您的数据。

我提出了一个可能更简单的替代解决方案:

创建一个对象,其中包含您的路径作为键,以及对相关驱动程序数组的引用作为值。

var mapping = {};
function storeMap (chain, data) {
    for (var i = 0; i < data.length; i++) {
        var updatedChain = (chain && chain + '/') + data[i].name;
        mapping[updatedChain] = data[i].drivers;
        if (data[i].drivers.length) {
            storeMap (updatedChain, data[i].drivers);
        }
    }
}

storeMap('', [data]);

然后添加你的项目:

var itemToAdd = { "name": "KIA", "drivers":[] };
var path = 'McLaren/BMW/Subaru/saab';
mapping[path].push(itemToAdd);

这应该是一次性的......就可重用性而言:你必须每次运行地图存储并不是非常有效。您可以做的是在您修改地图时更新地图的方法:

function addItem (item) {
    mapping[path].push(item);
    mapping[path + '/' + item.name] = item.drivers;
}

function removeItem (item) {
    var parentPath = item.name.split('/').slice(0, -1).join('/');
    var drivers = mapping[parentPath].drivers;
    drivers.splice(drivers.indexOf(item), 1);
    delete mapping[item.name];
}

答案 2 :(得分:1)

只是另一种解决方案,它将对象和路径作为数组。

&#13;
&#13;
function find(object, path) {
    if (object.name.toLowerCase !== path.shift().toLowerCase) {
        return;
    }
    return (!path.length || object.drivers.some(function (a) {
        object = find(a, path.slice());
        return object;
    })) && object;
}

var data = { "name": "McLaren", "drivers": [{ "name": "BMW", "drivers": [{ "name": "VW", "drivers": [] }, { "name": "Subaru", "drivers": [{ "name": "Saab", "drivers": [{ "name": "Lexus", "drivers": [] }, { "name": "Honda", "drivers": [] }] }] }] }] },
    path = 'McLaren/BMW/Subaru/Saab',
    object = { "name": "KIA", "drivers": [] };

find(data, path.split('/')).drivers.push(object);
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
&#13;
&#13;
&#13;