Выровнять глубоко вложенный массив с объектами и массивами - PullRequest
2 голосов
/ 31 марта 2020

У меня есть массив объектов, которые содержат другой массив с объектами. Вложенность в четыре уровня. Структура массива:

[
  {
    title: 'Title',
    type: 'section',
    links: [
      {
        label: 'Label',
        id: 'id_1',
        links: [
          {
            title: 'Title',
            type: 'section',
            links: [
              {
                label: 'Label',
                id: 'id_2',
                links: [
                  {
                    label: 'Label',
                    id: 'id_3',
                    links: [],
                  }
                ]
              }
            ]
          },
          {
            title: 'Other title',
            type: 'section',
            links: [
              {
                label: 'Label',
                id: 'id_4',
                links: [],
              }
            ]
          }
        ]
      }
    ]
  }
]

Я хочу иметь плоский массив с идентификаторами массивов ссылок, которые содержат ссылки (они являются родителями подменю). Таким образом, желаемый результат выглядит так: ["id_1", "id_2"]

Я попытался получить результат с помощью этой функции, взятой из MDN :

flatDeep(arr, d = 1) {
  return d > 0
    ? arr.reduce((acc, val) =>
      acc.concat(Array.isArray(val.links)
        ? this.flatDeep(val.links, d - 1)
        : val.links), [])
    : arr.slice();
}

Это дает мне пустое массив.

Ответы [ 5 ]

0 голосов
/ 31 марта 2020

Вот нерекурсивная версия.

const data = [{title:'Title',type:'section',links:[{label:'Label',id:'id_1',links:[{title:'Title',type:'section',links:[{label:'Label',id:'id_2',links:[{label:'Label',id:'id_3',links:[]}]}]},{title:'Other title',type:'section',links:[{label:'Label',id:'id_4',links:[]}]}]}]}];

const stack = data.slice();
const result = [];

let obj;
while (obj = stack.shift()) {
  if ("id" in obj && obj.links.length > 0) result.push(obj.id);
  stack.push(...obj.links);
}

console.log(result);

При этом сначала используется дыхание, но сначала его можно легко изменить на глубину. Вам нужно только изменить stack.push вызов на stack.unshift.

Для более подробного объяснения этих двух вопросов ознакомьтесь с Ширина сначала против глубины сначала .

0 голосов
/ 31 марта 2020

Используйте Array.flatMap(). Уничтожить каждый объект и использовать пустой массив по умолчанию для пропущенных значений id. Concat id и результат рекурсивного выравнивания ссылок.

const flattenIds = arr => arr.flatMap(({ id = [], links }) => 
  [].concat(id, flattenIds(links))
);
    
const data = [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_1', links: [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_2', links: [{ label: 'Label', id: 'id_3', links: [] }] }] }, { title: 'Other title', type: 'section', links: [{ label: 'Label', id: 'id_4', links: [] }] }] }] }];

const result = flattenIds(data);

console.log(result);
0 голосов
/ 31 марта 2020

Вы можете получить плоский массив с рекурсией и проверкой на id на отсутствие свойства.

const
    getId = ({ id, links }) => [
        ...(id === undefined ? [] : [id]),
        ...links.flatMap(getId)
    ],
    data = [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_1', links: [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_2', links: [{ label: 'Label', id: 'id_3', links: [] }] }] }, { title: 'Other title', type: 'section', links: [{ label: 'Label', id: 'id_4', links: [] }] }] }] }],
    result = data.flatMap(getId);

console.log(result);
0 голосов
/ 31 марта 2020

var array = JSON.parse('[{"title":"Title","type":"section","links":[{"label":"Label","id":"id_1","links":[{"title":"Title","type":"section","links":[{"label":"Label","id":"id_2","links":[{"label":"Label","id":"id_3","links":[]}]}]},{"title":"Other title","type":"section","links":[{"label":"Label","id":"id_4","links":[]}]}]}]}]');


arr = [];
 while(array.length != 0) {
  var ob1 = array.splice(0,1)[0];
  for(var ob2 of ob1.links) {
    if (ob2.links.length !== 0) {
      arr.push(ob2.id);
      array = array.concat(ob2.links);
    }
  }
 }

console.log(arr);

Вот вывод, который вы запросили:

[
  "id_1",
  "id_2"
]
0 голосов
/ 31 марта 2020

Я думаю, что рекурсивная функция упростит. (рекурсивно ищите массив lists и pu sh the id в res).

const data = [
  {
    title: "Title",
    type: "section",
    links: [
      {
        label: "Label",
        id: "id_1",
        links: [
          {
            title: "Title",
            type: "section",
            links: [
              {
                label: "Label",
                id: "id_2",
                links: [
                  {
                    label: "Label",
                    id: "id_3",
                    links: []
                  }
                ]
              }
            ]
          },
          {
            title: "Other title",
            type: "section",
            links: [
              {
                label: "Label",
                id: "id_4",
                links: []
              }
            ]
          }
        ]
      }
    ]
  }
];

const res = [];

const ids = data => {
  data.forEach(item => {
    if ("id" in item) {
      res.push(item.id);
    }
    if (item.links) {
      ids(item.links);
    }
  });
};

ids(data);
console.log(res);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...