Задать вопрос
@anastasia__galkina

Как преобразовать древовидный массив в плоский?

Есть древовидный массив:
[
  {
    "task": "Project: Shopping",
    "duration": 13.25,
    "user": "Tommy Maintz",
    "iconCls": "task-folder",
    "expanded": true,
    "children": [
      {
        "task": "Housewares",
        "duration": 1.25,
        "user": "Tommy Maintz",
        "iconCls": "task-folder",
        "children": [
          {
            "task": "Kitchen supplies",
            "duration": 0.25,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task"
          }, {
            "task": "Groceries",
            "duration": .4,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task",
            "done": true
          }, {
            "task": "Cleaning supplies",
            "duration": .4,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task"
          }, {
            "task": "Office supplies",
            "duration": .2,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task"
          }
        ]
      }, {
        "task": "Remodeling",
        "duration": 12,
        "user": "Tommy Maintz",
        "iconCls": "task-folder",
        "expanded": true,
        "children": [
          {
            "task": "Retile kitchen",
            "duration": 6.5,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task"
          }, {
            "task": "Paint bedroom",
            "duration": 2.75,
            "user": "Tommy Maintz",
            "iconCls": "task-folder",
            "children": [
              {
                "task": "Ceiling",
                "duration": 1.25,
                "user": "Tommy Maintz",
                "iconCls": "task",
                "leaf": true
              }, {
                "task": "Walls",
                "duration": 1.5,
                "user": "Tommy Maintz",
                "iconCls": "task",
                "leaf": true
              }
            ]
          }, {
            "task": "Decorate living room",
            "duration": 2.75,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task",
            "done": true
          }, {
            "task": "Fix lights",
            "duration": .75,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task",
            "done": true
          }, {
            "task": "Reattach screen door",
            "duration": 2,
            "user": "Tommy Maintz",
            "leaf": true,
            "iconCls": "task"
          }
        ]
      }
    ]
  }, {
    "task": "Project: Testing",
    "duration": 2,
    "user": "Core Team",
    "iconCls": "task-folder",
    "children": [
      {
        "task": "Mac OSX",
        "duration": 0.75,
        "user": "Tommy Maintz",
        "iconCls": "task-folder",
        "children": [
          {
            "task": "FireFox",
            "duration": 0.25,
            "user": "Tommy Maintz",
            "iconCls": "task",
            "leaf": true
          }, {
            "task": "Safari",
            "duration": 0.25,
            "user": "Tommy Maintz",
            "iconCls": "task",
            "leaf": true
          }, {
            "task": "Chrome",
            "duration": 0.25,
            "user": "Tommy Maintz",
            "iconCls": "task",
            "leaf": true
          }
        ]
      }, {
        "task": "Windows",
        "duration": 3.75,
        "user": "Darrell Meyer",
        "iconCls": "task-folder",
        "children": [
          {
            "task": "FireFox",
            "duration": 0.25,
            "user": "Darrell Meyer",
            "iconCls": "task",
            "leaf": true
          }, {
            "task": "Safari",
            "duration": 0.25,
            "user": "Darrell Meyer",
            "iconCls": "task",
            "leaf": true
          }, {
            "task": "Chrome",
            "duration": 0.25,
            "user": "Darrell Meyer",
            "iconCls": "task",
            "leaf": true
          }, {
            "task": "Internet Explorer",
            "duration": 3,
            "user": "Darrell Meyer",
            "iconCls": "task",
            "leaf": true
          }
        ]
      }, {
        "task": "Linux",
        "duration": 0.5,
        "user": "Aaron Conran",
        "iconCls": "task-folder",
        "children": [
          {
            "task": "FireFox",
            "duration": 0.25,
            "user": "Aaron Conran",
            "iconCls": "task",
            "leaf": true
          }, {
            "task": "Chrome",
            "duration": 0.25,
            "user": "Aaron Conran",
            "iconCls": "task",
            "leaf": true
          }
        ]
      }
    ]
  }
]

Вложенные массивы находятся в поле children.

Нужно преобразовать данный массив в плоский такого вида:

[
  {
    "task": "Project: Shopping",
    "duration": 13.25,
    "user": "Tommy Maintz",
    "iconCls": "task-folder",
    "expanded": true,
  }, 
  {
    "task": "Housewares",
    "duration": 1.25,
    "user": "Tommy Maintz",
    "iconCls": "task-folder",
  }, 
  { 
    "task": "Kitchen supplies",
    "duration": 0.25,
    "user": "Tommy Maintz",
    "leaf": true,
    "iconCls": "task"
  },
  ...
]
  • Вопрос задан
  • 176 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Рекурсия есть:

const getFromTree = (tree, childrenKey, getter = n => n) =>
  Array.isArray(tree)
    ? tree.flatMap(n => [
        getter(n),
        ...getFromTree(n[childrenKey], childrenKey, getter),
      ])
    : [];

// или

function* flatTree(tree, childrenKey) {
  if (
    tree instanceof Object &&
    tree[Symbol.iterator] instanceof Function
  ) {
    for (const n of tree) {
      yield n;
      yield* getFromTree(n[childrenKey], childrenKey);
    }
  }
}

Рекурсии нет:

const getFromTree = function(tree, childrenKey, getter = n => n) {
  const result = [];

  for (const stack = this(tree); stack.length;) {
    const n = stack.pop();
    result.push(getter(n));
    stack.push(...this(n[childrenKey]));
  }

  return result;
}.bind(x => x instanceof Array ? [...x].reverse() : []);

// или

const flatTree = function*(tree, childrenKey) {
  const stack = [];

  for (let [ i, arr ] = this(tree); ++i < arr.length || stack.length;) {
    if (i === arr.length) {
      [ i, arr ] = stack.pop();
    } else {
      yield arr[i];
      stack.push([ i, arr ]);
      [ i, arr ] = this(arr[i][childrenKey]);
    }
  }
}.bind(x => [ -1, x?.constructor === Array ? x : [] ]);

Получаем массив:

// если использовать обычную функцию
const result = getFromTree(tree, 'children', ({ children, ...n }) => n);
// или, генератор
const result = Array.from(flatTree(tree, 'children'), ({ children, ...n }) => n);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы