Как слить и вернуть новый массив из объекта в es6 - PullRequest
10 голосов
/ 25 марта 2019

Предположим, есть два объекта.

const a = [
  { id: '1-1-1', name: 'a111' },
  { id: '1-1-2', name: 'a112' },
  { id: '1-2-1', name: 'a121' },
  { id: '1-2-2', name: 'a122' },
  { id: '2-1-1', name: 'a211' },
  { id: '2-1-2', name: 'a212' }
]
const b = ['1-1', '1-2', '2-1']

и результат

  {

      '1-1':[
        { id: '1-1-1', name: 'a111' },
        { id: '1-1-2', name: 'a112' },
      ],
      '1-2':[
          { id: '1-2-1', name: 'a121' },
          { id: '1-2-2', name: 'a122' },
      ],
      '2-1':[
        { id: '2-1-1', name: 'a211' },
        { id: '2-1-2', name: 'a212' },
      ]
    }

По сути, я хочу сгруппировать данные.

Я использую includes, чтобы проверить, соответствует ли элемент из b идентификатору из a. Затем создайте новый массив.

Это моя попытка ( скрипка ):

return b.map(item => a.map(jtem => {
  if(jtem.id.includes(item)){
    return {
      [item]: jtem
    }
  }
}))

Почему-то это не работает.

и есть ли умный способ избежать вложенного цикла for или функции map?

1 Ответ

13 голосов
/ 25 марта 2019

Вы можете сделать это в следующих шагах:

  • Применить reduce() к массиву b

  • Во время каждой итерации используйте filter() в массиве a

  • Получить все элементы из a, который начинается с элемента b, используя String.prototype.startsWith()
  • Наконец, установите его как свойство ac и верните ac

const a = [
  { id: '1-1-1', name: 'a111' },
  { id: '1-1-2', name: 'a112' },
  { id: '1-2-1', name: 'a121' },
  { id: '1-2-2', name: 'a122' },
  { id: '2-1-1', name: 'a211' },
  { id: '2-1-2', name: 'a212' }
]
const b = ['1-1', '1-2', '2-1']

let res = b.reduce((ac,b) => {
  
  ac[b] = a.filter(x => x.id.startsWith(b));
  return ac;

},{})
console.log(res)

В соответствии с комментариями @Falco, было бы лучше отсканировать a один раз как его большое значение.Так что вот эта версия. На самом деле, она лучше в отношении производительности

const a = [
  { id: '1-1-1', name: 'a111' },
  { id: '1-1-2', name: 'a112' },
  { id: '1-2-1', name: 'a121' },
  { id: '1-2-2', name: 'a122' },
  { id: '2-1-1', name: 'a211' },
  { id: '2-1-2', name: 'a212' }
]
const b = ['1-1', '1-2', '2-1']


let res = a.reduce((ac,x) => {
  let temp = b.find(y => x.id.startsWith(y))
  if(!ac[temp]) ac[temp] = [];
  ac[temp].push(x);
  return ac;
},{})

console.log(res)

Примечание : startsWith не поддерживается IE, поэтому вы можете создавать полифилл с помощью indexOf

if(!String.prototype.startWith){
  String.prototype.startsWith = function(str){
    return this.indexOf(str) === 0
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...