сплющить массив объектов javascript

1

У меня есть массив объектов с иерархической структурой, что-то вроде этого:

[
    {name: 'ParentOne', children: [
        {name: 'ParentOneChildOne'},
        {name: 'ParentOneChildTwo', children: [
            {name: 'ParentOneChildTwoGrandChildOne'},
        ]},
    ]}, 
    {name: 'ParentTwo', children: [
        {name: 'ParentTwoChildOne', children: [
           {name: 'ParentTwoChildOneGrandChildOne'},
           {name: 'ParentTwoChildOneGrandChildTwo'}
        ]},
        {name: 'ParentTwoChildTwo'}
    ]}
];

Я хочу сгладить его:

[
    {name: 'ParentOne'},
    {name: 'ParentOneChildOne'},
    {name: 'ParentOneChildTwo'},
    {name: 'ParentOneChildTwoGrandChildOne'},
    {name: 'ParentTwo'},
    {name: 'ParentTwoChildOne'},
    {name: 'ParentTwoChildOneGrandChildOne'},
    {name: 'ParentTwoChildOneGrandChildTwo'},
    {name: 'ParentTwoChildTwo'}
]

Я пробовал _.flatten() и _.flatMap(), но он не создает то, что мне нужно. Каков наилучший способ его достижения, предпочтительно используя lodash.js или underscore.js.

Теги:
lodash
underscore.js
flatten

5 ответов

5
Лучший ответ

Не нужно подчеркивать /lodash.

const arr = [
    {name: 'ParentOne', children: [
        {name: 'ParentOneChildOne'},
        {name: 'ParentOneChildTwo', children: [
            {name: 'ParentOneChildTwoGrandChildOne'},
        ]},
    ]}, 
    {name: 'ParentTwo', children: [
        {name: 'ParentTwoChildOne', children: [
           {name: 'ParentTwoChildOneGrandChildOne'},
           {name: 'ParentTwoChildOneGrandChildTwo'}
        ]},
        {name: 'ParentTwoChildTwo'}
    ]}
];

function flatten(arr) {
    return arr? arr.reduce((result, item) => [
        ...result,
        { name: item.name },
        ...flatten(item.children)
    ], []) : [];
}

console.log(flatten(arr));
2

Рекурсивные функции - это путь для любой глубины итерации.

С некоторыми ES2015 и LoDash/Underscore

var arr = [{
  name: 'ParentOne',
  children: [{
    name: 'ParentOneChildOne'
  }, {
    name: 'ParentOneChildTwo',
    children: [{
      name: 'ParentOneChildTwoGrandChildOne'
    }, ]
  }, ]
}, {
  name: 'ParentTwo',
  children: [{
    name: 'ParentTwoChildOne',
    children: [{
      name: 'ParentTwoChildOneGrandChildOne'
    }, {
      name: 'ParentTwoChildOneGrandChildTwo'
    }]
  }, {
    name: 'ParentTwoChildTwo'
  }]
}];

var res = _.reduce(arr, (a, b) => {
  (rec = item => {
    _.each(item, (v, k) => (_.isObject(v) ? rec(v) : a.push(_.zipObject([k], [v]))))
  })(b);
  return a;
}, []);

console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
1

Я бы использовал .reduce и .reduce чтобы сделать это. Здесь моя реализация с использованием Array.reduce, но вы можете сделать то же самое с функцией сокращения подчеркивания.

const arr = [
    {name: 'ParentOne', children: [
        {name: 'ParentOneChildOne'},
        {name: 'ParentOneChildTwo', children: [
            {name: 'ParentOneChildTwoGrandChildOne'},
        ]},
    ]}, 
    {name: 'ParentTwo', children: [
        {name: 'ParentTwoChildOne', children: [
           {name: 'ParentTwoChildOneGrandChildOne'},
           {name: 'ParentTwoChildOneGrandChildTwo'}
        ]},
        {name: 'ParentTwoChildTwo'}
    ]}
];

function flatten(arr) {
   return arr.reduce((result, current) => {
      if (current.children) {
         const children = flatten(current.children);
         delete current.children;
         result.push(current);
         result.push(...children);
      } else {
         result.push(current);
      }
      return result;
   }, [])
}

console.log(flatten(arr));
0

Вы можете использовать некоторое уничтожение и использовать рекурсивную функцию для сбора всех необходимых предметов.

var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
    flat = (r, { name, children = [] }) => [...r, { name }, ...children.reduce(flat, []) ],
    result = array.reduce(flat, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

В EDGE вам нужно другое использование значений defualt

var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
    flat = (r, { name, children }) => [...r, { name }, ...(children || []).reduce(flat, []) ],
    result = array.reduce(flat, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0

Вы можете попытаться адаптировать функцию flatten данную в этом ответе, и слегка перевернуть логику в свою структуру объекта.

//Your object
var data = [{
    name: 'ParentOne',
    children: [{
        name: 'ParentOneChildOne'
      },
      {
        name: 'ParentOneChildTwo',
        children: [{
          name: 'ParentOneChildTwoGrandChildOne'
        }, ]
      },
    ]
  },
  {
    name: 'ParentTwo',
    children: [{
        name: 'ParentTwoChildOne',
        children: [{
            name: 'ParentTwoChildOneGrandChildOne'
          },
          {
            name: 'ParentTwoChildOneGrandChildTwo'
          }
        ]
      },
      {
        name: 'ParentTwoChildTwo'
      }
    ]
  }
];

//georg flatten function
flatten = function(x, result, prefix) {
  if (_.isObject(x)) {
    _.each(x, function(v, k) {
      flatten(v, result, prefix ? prefix + '_' + k : k)
    })
  } else {
    result[prefix] = x
  }
  return result
}

//using the function on your data
result = flatten(data, {});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Помогает ли это вообще?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню