Как добавить пару ключ-значение к объекту древовидной структуры с помощью lodash - PullRequest
1 голос
/ 22 июня 2019

Мне нужно добавить пару ключ-значение в конце дерева, как объект json.

[{
    "name": "minpur",
    "children": [{
        "name": "ppp1",
        "children": [{
            "name": "feeder",
            "children": [{
                "name": "rmu16",
                "children": [{
                    "name": "invt16",
                    "children": [{
                        "aname": "inv 01"
                    }]
                }]
            }]
        }]
    }]
}]

Ожидается

[{
  "name": "minpur",
  "children": [{
    "name": "ppp1",
    "children": [{
      "name": "feeder",
      "children": [{
        "name": "rmu16",
        "children": [{
          "name": "invt16",
          "children": [{
            "aname": "inv 01",
            **
            "value": 300 **
          }]
        }]
      }]
    }]
  }]
}]

попробовал рекурсивную функцию, как показано ниже

let traverse = function(jsonObj) {
  if (jsonObj !== null && typeof jsonObj == "object") {
    return Object.entries(jsonObj).forEach(([key, value]) => {
      if (key != "aname") {
        traverse(value);
      } else {
        return value;
      }
    });
  }
}

Ответы [ 4 ]

1 голос
/ 22 июня 2019

Проверьте, существует ли ключ aname на объекте, и добавьте свойство, если оно есть. Если он не выполняет итерации дочерних элементов с Array.forEach(), и вызывает travers для дочерних элементов.

const traverse = (key, value) => obj => {
  const inner = obj => {
    if(obj.hasOwnProperty(key)) obj.value = value
    else obj.children.forEach(inner)
  }
  
  return inner(obj)
}

const tree = [{"name":"minpur","children":[{"name":"ppp1","children":[{"name":"feeder","children":[{"name":"rmu16","children":[{"name":"invt16","children":[{"aname":"inv 01"}]}]}]}]}]}]

tree.forEach(traverse('aname', 300))

console.log(tree)
0 голосов
/ 22 июня 2019

Вы можете создать рекурсивную функцию, которая обходит массивы объектов и объединяет найденный объект (по указанному key name) с указанным вами аргументом. No lodash необходимо:

let data = [{ "name": "minpur", "children": [{ "name": "ppp1", "children": [{ "name": "feeder", "children": [{ "name": "rmu16", "children": [{ "name": "invt16", "children": [{ "aname": "inv 01" }] }] }] }] }] }]

let deepSetByKey = (a, k, setObj) =>
  a.forEach(o => k in o ? Object.assign(o, setObj) : 
   'children' in o ? deepSetByKey(o.children, k, setObj) : 0) && a

deepSetByKey(data, 'aname', { value: 300 }) // call the fn

console.log(data[0].children[0].children[0].children[0].children[0].children[0])

Идея состоит в том, чтобы рекурсивно перемещаться с Array.forEach и использовать Object.assign , когда вы найдете нужную в текущем объекте опору.

0 голосов
/ 22 июня 2019

Если вы хотите использовать JS служебную библиотеку lodash, она дает вам много методов для обработки таких сложных структур.

Для этого я бы предложил _.set - https://lodash.com/docs/4.17.11#set

const _u = _.noConflict(); 
var object = { 'a': [{ 'b': { 'c': 3 } }] };
 
_u.set(object, 'a[0].b.c', 4);
console.log(object);
// => 4
 
_u.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object);
// => 5
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
0 голосов
/ 22 июня 2019

Вот более функциональное решение, в котором исходные значения не изменены.Дочерние элементы проверяются, и если нет дочерних элементов, переданные ключи используются для расширения текущего узла.

const obj = [{
  "name": "minpur",
  "children": [{
    "name": "ppp1",
    "children": [{
      "name": "feeder",
      "children": [{
        "name": "rmu16",
        "children": [{
          "name": "invt16",
          "children": [{
            "aname": "inv 01"
          }]
        }]
      }]
    }]
  }]
}]

function addToLeaf(append, node) {
  if (!node.children) {
    return {
      ...node,
      ...append
    }
  }
  return { 
    ...node,
    ...{ children: node.children.map(child => addToLeaf(append, child))}
  }
}

const result = obj.map((node) => addToLeaf({
  value: 300
}, node));

console.log(result);
...