Как рекурсивно добавить пары ключ-значение объекта в массив объектов с дочерними массивами? - PullRequest
1 голос
/ 25 марта 2020

Я все еще изучаю веревки рекурсии, и я хотел бы добавить 'isChecked: false' к каждому объекту в этом вложенном дереве массивов.

const nestedMap = (arr) => {
  const result = arr.map(row => {
    if (row.children.length) {
      const children = row.children.map(child => {
        return { ...child, isChecked: false };
      });
      return { ...row, isChecked: false, children };
    } else {
      return { ...row, isChecked: false };
    }
  });
  return result[0].children[0]
}

nestedMap([{title: 'page1', children: [{title: 'page2', children: [{title: 'page4'}]}, {title: 'page3'}]}, {title: 'page5', children: []}])

Вот мой результат - как вы можете видите, я успешно обновляю первый набор детей, но не остальных.

{ title: 'page2',
  children: [ { title: 'page4' } ],
  isChecked: false } 

Я знаю, что должен вызывать функцию где-то внутри себя, но я идиот. Как всегда, любая помощь будет принята с благодарностью. Спасибо.

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Другая возможность - написать более обобщенную реализацию c nestedMap, а затем передать ей функцию, которая добавляет ваше свойство. Вот как я мог бы написать это:

const nestedMap = (fn) => (xs) => 
  xs .map (({children, ...rest}) => fn ({
    ... rest,
    ... (children ? {children: nestedMap (fn) (children)} : {})
  }))

const addProp = (key, val) => (obj) => 
  ({... obj, [key]: val})

const pages = [{title: 'page1', children: [{title: 'page2', children: [{title: 'page4'}]}, {title: 'page3'}]}, {title: 'page5', children: []}]

console .log (
  nestedMap (addProp ('checked', false)) (pages)
)

Эта версия не изменяет наш оригинал, но создает новый массив, полный новых объектов. (Это не делает полный клон; другие свойства наших узлов могут быть разделены ссылкой.)

addProp достаточно просто: он принимает ключ и значение и возвращает функция, которая получает объект, возвращая новый объект со всеми его свойствами и новым ключом / значением.

nestedMap рекурсивно отображает функцию в структуре node: {..., children: [more nodes]}. Предоставленная ей функция преобразования вызывается сначала (рекурсивно) для дочерних элементов каждого узла, а затем для самого узла.

1 голос
/ 25 марта 2020

Ваш if-оператор if (row.children.length) { проверяет, является ли row.children массивом длины> 0, поэтому здесь вы бы хотели снова вызвать nestedMap.

Попробуйте что-то вроде этого:

const nestedMap = (arr) => {
  const result = arr.map(row => {
    // check if row.children exists AND if its length exists / is greater than 0
    if (row.children && row.children.length) {
      const children = nestedMap(row.children);
      return { ...row, isChecked: false, children };
    } else {
      return { ...row, isChecked: false };
    }
  });
  // Note: You should probably return the entire result here, not result[0].children[0]
  return result;
}

let output = nestedMap([{title: 'page1', children: [{title: 'page2', children: [{title: 'page4'}]}, {title: 'page3'}]}, {title: 'page5', children: []}])

console.log(output)

Обратите внимание, что я сделал 3 изменения:

  1. if (row.children && row.children.length) {
    • Я добавил проверку, чтобы убедиться, что row.children существует , перед проверкой row.children.length
  2. const children = nestedMap(row.children);
    • Здесь мы делаем рекурсию:)
  3. return result;
    • Это вернет весь результат (исходный вложенный массив объектов, с isChecked: false в каждом объекте).
    • Примечание: я не уверен, почему вы завершили свою функцию с помощью result[0].children[0], который будет возвращать только первого потомка первого элемента исходного массива?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...