简体   繁体   English

对象数组中的递归循环

[英]recursive loop in objects arrays

Im working with at structure that may look something like this: 我正在处理看起来像这样的结构:

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

Its an object containing a name and an array of drivers . 它是一个包含namedrivers数组的对象。 drivers can be empty but it always exists. drivers可以为空,但始终存在。

Now lets say i have the following object: 现在说我有以下对象:

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

I need to place this object at the right place. 我需要将此对象放置在正确的位置。 To my help I got the following: 在我的帮助下,我得到了以下信息:

McLaren/BMW/Subaru/saab

So the new object should be pushed to the same array as Lexus and Honda. 因此,应将新对象与雷克萨斯和本田推到同一阵列。

I´ve been going crazy trying to figure out how to do it. 我一直在发疯,试图弄清楚该怎么做。 I have been thinking in the following lines: 我一直在思考以下几行:

I convert the path to an array: 我将路径转换为数组:

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

And try to use a recursive function: 并尝试使用递归函数:

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]")

            }
          }
        } 
      }

I feel like I am pretty close but there are some pieces missing. 我觉得我已经很接近了,但是缺少了一些东西。 Am I maybe thinking about recursion the wrong way or making it overly complicated? 我是否在考虑错误的递归方式或使其变得过于复杂? Help appreciated,thanks! 感谢帮助,谢谢!

EDIT: 编辑:

McLaren/BMW/Subaru/saab indicates the path to where the new object ( KIA ) should go. McLaren/BMW/Subaru/saab指示新对象( KIA )应该到达的路径。 So KIA should go in the drivers -arr in the object with the name saab . 因此, KIA应该将drivers -arr放入名称为saab的对象中。

recursiveFunc() checks in which array the path-name exists and the then tries to use this objects array to go deeper into the object in order to find the last part of the path (saab, in this case). recursiveFunc()检查路径名存在于哪个数组中,然后尝试使用此对象数组更深入对象,以找到路径的最后一部分(在这种情况下为saab)。 The new object should be pushed to this array. 新对象应推送到此数组。

You can run this code passing { drivers : [data] } root object as currentNode . 您可以通过将{ drivers : [data] }根对象作为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;
}

Note that in your example you have Saab in JSON and saab in path which will lead path search failure. 请注意,在您的示例中,JSON中包含Saab ,路径中包含saab ,这将导致路径搜索失败。

Here's an idea to stand by: when the data is difficult to deal with, transform your data. 这是一个备用的想法:当数据难以处理时,请转换数据。

I propose an alternative solution that might be a little simpler: 我提出了一个可能更简单的替代解决方案:

Create an object which contains your path as a key, and a reference to the associated driver array as the value. 创建一个对象,该对象包含路径作为键,并包含对关联驱动程序数组的引用作为值。

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

Then to add your item: 然后添加您的项目:

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

This was meant to be a once off... on the case of reusability: you'd have to run the map storing every time which isn't very efficient. 在可重用性的情况下,这本来应该是一次过的事情:您必须每次都运行地图存储,这不是很有效。 What you could do is have methods that update the map as you're modifying it: 您可以做的是拥有一些在修改地图时更新地图的方法:

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];
}

Just another solution, which takes the object and the path as array. 另一个解决方案,将对象和路径作为数组。

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

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

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