在json数组中查找值并将另外一个json数组追加到value的父节点。(优化)

时间:2018-06-18 11:00:26

标签: javascript jquery arrays json

我有以下JSON数组作为输入

var trees = [
  {
    name: "alex",
    lastname: "watson",
    city: "California",
    state: "Alameda",
    childrens: [
      { name: "shane watson", city: "Troy", state: "Alabama" },
      {
        name: "adam watson",
        city: "Palmer",
        state: "Alaska",
        childrens: [
          { name: "ana watson", city: "Avondale", state: "Arizona" },
          { name: "ama watson", city: "Douglas", state: "Arizona" }
        ]
      }
    ]
  },
  {
    name: "adam",
    lastname: "ronaldo",
    city: "Bradenton",
    state: "Florida",
    childrens: [
      { name: "austin ronaldo", city: "Alhambra", state: "California" },
      {
        name: "kira ronaldo",
        city: "Calexico",
        state: "California",
        childrens: [
          { name: "sam ronaldo", city: "Chico", state: "California" },
          {
            name: "godwin ronaldo",
            city: "Eureka",
            state: "California",
            childrens: [
              { name: "michael ronaldo", city: "Buffalo", state: "New York" }
            ]
          }
        ]
      }
    ]
  }
];
  1. 找出JSON数组变量树中的城市(例如,city =“Buffalo”或name =“Godwin ronaldo”)
  2. 将另一个节点添加到该路径(例如,添加此节点=> {name:'alver ronaldo',city:'Athens',state:'Ohio'}其中city =“Buffalo”或 name =“godwin ronaldo”)
  3.   

    注意:树变量应该更新,当我做console.log(树)   它应该给我带有更新节点的完整数组

    我试图谷歌大量的解决方案,但没有奏效,当它的工作他们得到太多笨重的代码&有时他们不更新主根变量只是参与其他变量并更新它。

    以下是小提琴 https://jsfiddle.net/3kt52fpd/31/

    它一直工作到路径 - 我能够使用eval函数获取路径的路径和控制台值但不能将值附加到该路径。 我在这里先向您的帮助表示感谢!!!!

1 个答案:

答案 0 :(得分:1)

Given the trees variable above...

This function will depth-first walk a list of tree nodes, passing each one to the predicate function given, and returning the ones that match.

function findMatchingNodes(nodes, predicate) {
  const results = [];
  function walk(node) {
    if (predicate(node)) {
      results.push(node);
    }
    (node.childrens || []).forEach(walk);
  }
  nodes.forEach(walk);
  return results;
}

We can then use this to find the matching nodes:

const matches = findMatchingNode(
  trees,
  (n) => n.city === 'Buffalo' || n.name === 'godwin ronaldo'
);

And then we can use Array.forEach to update those in-place to add the new nodes:

matches.forEach(node => {
  const children = node.childrens || (node.childrens = []); // Ensures there is a childrens array
  children.push({ name: "alver ronaldo", city: "Athens", state: "Ohio" });
});

And so, when we console.log the treesvariable, the two matching nodes have indeed new children:

// ... snip ...
{
  name: "godwin ronaldo",
  city: "Eureka",
  state: "California",
  childrens: [
    {
      name: "michael ronaldo",
      city: "Buffalo",
      state: "New York",
      childrens: [
        {
          name: "alver ronaldo",
          city: "Athens",
          state: "Ohio"
        }
      ]
    },
    {
      name: "alver ronaldo",
      city: "Athens",
      state: "Ohio"
    }
  ]
}

Full JSfiddle here: https://jsfiddle.net/5sve3nxc/

Edit – also accessing the node parents

If you need to access the full path from the tree root to the matching node, you can use something like

function findMatchingNodePaths(nodes, predicate) {
  const results = [];
  function walk(node, parents) {
    const path = parents.concat(node);
    if(predicate(node)) {
      results.push(path);
    }
    (node.childrens || []).forEach((node) => walk(node, path));
  }
  nodes.forEach((node) => walk(node, []));
  return results;
}

in which case the result array contains arrays of nodes, where the last one is the matching node.