根据值查找最后嵌套的n次对象

时间:2019-06-05 18:58:34

标签: javascript arrays object

试图自己解决该任务,但我放弃了。无论我尝试了什么,那都行不通。因此决定在这里寻求帮助。

有一个物体:

var obj = [{
    "name": "111",
    "type": "folder",
    "expanded": true,
    "id": 0,
    "items": [
      {
        "name": "222",
        "type": "folder",
        "expanded": true,
        "id": 1,
        "items": [
          {
            "name": "333",
            "type": "folder",
            "expanded": true,
            "id": 2,
            "items": [
              {
                "name": "444",
                "type": "folder",
                "expanded": true,
                "id": 3,
                "items": [],
                "itemIndex": 0,
                "index": 0
              }
            ],
            "itemIndex": 0,
            "index": 0
          }
        ],
        "itemIndex": 0,
        "index": 0
      }
    ],
    "itemIndex": 0,
    "index": 0
  }]

深度可能会有所不同,但是每个级别的键集始终相同。 我需要确定最可能的水平。

考虑到上面的代码,比方说,我需要一个功能,即仅具有其 ID name ,可以将另一个对象推入以下对象的“ items”数组中:

{
    "name": "444",
    "type": "folder",
    "expanded": true,
    "id": 3,
    "items": [],
    "itemIndex": 0,
    "index": 0
}

换句话说,我有一个输入文本和一个按钮。输入文本并单击该按钮后,函数应确定给定对象的最后一级,然后推送一个新生成的对象(同一组键, ID 应为继承对象的 +1)名称应从输入的文本字段字符串中输入)。

我希望我尽可能详细地解释问题。

2 个答案:

答案 0 :(得分:1)

您将需要一个首先找到最深节点的函数:

/**
 * Return [depth, item] where item is the deepest subnode of node.
 */
function find_deepest(node, depth=0) {
    if (node.items.length === 0) return [depth, node];

    return node.items.map(child => find_deepest(child, depth+1)).sort().reverse()[0];
}

那么就很简单:

const [depth, node] = find_deepest(obj, 0);
node.items.push({...});

更新:刚刚意识到您的obj是一个列表,因此使用上面的代码,它看起来像这样:

const [depth, node] = obj.map(child => find_deepest(child)).sort().reverse()[0]);

这不是最大的界面。

将递归分为两个函数,一个用于节点大小写,一个用于数组大小写,然后将它们包装在一个按类型分支的函数中,将为您提供一个更好的接口:

console.log(find_deepest(obj));

有关详细信息,请参见下面的代码片段(我用另一个带有空项目的分支扩展了您的obj:

var obj = [{
    "name": "111", "type": "folder", "expanded": true, "id": 0, "itemIndex": 0, "index": 0,
    "items": [{
        "name": "222", "type": "folder", "expanded": true, "id": 1, "itemIndex": 0, "index": 0,
        "items": [{
            "name": "333", "type": "folder", "expanded": true, "id": 2, "itemIndex": 0, "index": 0,
            "items": [{
                "name": "444", "type": "folder", "expanded": true, "id": 3,"itemIndex": 0, "index": 0,
                "items": []
            }],
        }, {
            "name": "555", "type": "folder", "expanded": true, "id": 3,"itemIndex": 0, "index": 0,
            "items": [{
                "name": "666", "type": "folder", "expanded": true, "id": 3,"itemIndex": 0, "index": 0,
                "items": [{
                    "name": "777", "type": "folder", "expanded": true, "id": 3,"itemIndex": 0, "index": 0,
                    "items": [],
                }]
            }]
        }]
    }]
}];

function find_deepest(val, depth=0) {
    function _find_deepest_node(node, depth) {
        if (node.items.length === 0) return [depth, node];
        return _find_deepest_array(node.items, depth + 1);
    }

    function _find_deepest_array(arr, depth) {
        return arr.map(child => _find_deepest_node(child, depth)).sort().reverse()[0];
    }

    if (Array.isArray(val)) {
        return _find_deepest_array(val, depth)[1];  // get the node, not the depth..
    } else {
        return _find_deepest_node(val, depth)[1];
    }
}

console.log(find_deepest(obj));

答案 1 :(得分:0)

我将创建一个递归函数,一旦找到正确的ID,它将把数据推送到数组的末尾。如果找不到ID,请转到下一项。看起来像这样:

function pushItem(id, data, obj) {
  for (let itm of obj) {
    let r = itm.items.find(i => i.id == id)
    if(!r) return pushItem(id, data, itm.items)
    r.items.push(data)
  }
}

pushItem(3, {abc: 1}, obj)
console.log(obj)

这是一个有效的示例:

var obj = [{
  "name": "111",
  "type": "folder",
  "expanded": true,
  "id": 0,
  "items": [{
    "name": "222",
    "type": "folder",
    "expanded": true,
    "id": 1,
    "items": [{
      "name": "333",
      "type": "folder",
      "expanded": true,
      "id": 2,
      "items": [{
        "name": "444",
        "type": "folder",
        "expanded": true,
        "id": 3,
        "items": [],
        "itemIndex": 0,
        "index": 0
      }],
      "itemIndex": 0,
      "index": 0
    }],
    "itemIndex": 0,
    "index": 0
  }],
  "itemIndex": 0,
  "index": 0
}]

function pushItem(id, data, obj) {
  for (let itm of obj) {
    let r = itm.items.find(i => i.id == id)
    if (!r) return pushItem(id, data, itm.items)
    r.items.push(data)
  }
}

pushItem(3, { name: "123123", id: 20, items: [] }, obj)
console.log(obj)