Как объединить значение объекта массива в массив, если есть одинаковый идентификатор - PullRequest
2 голосов
/ 16 мая 2019

Я хочу объединить значение в массив, если у него одинаковый идентификатор. У меня есть один массив таких объектов.

[ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Rosie',
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Lisa',
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: 'Jennie',
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Jisoo',
 },
]

и я хочу объединить ключ favorite из строки в массив. Я хочу вывод, как это

[ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: ['Rosie', 'Lisa', 'Jisoo'],
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: ['Jennie'],
 } 

и я пытаюсь написать код, подобный следующему: (от: Суммирование схожих ключей в массиве объектов )

var obj = [
    {
      id: 'Tony',
      type: 'hero',
      favorite: 'Rosie',
    },
    {
      id: 'Jane',
      type: 'human',
      favorite: null,
    },
    {
      id: 'Tony',
      type: 'hero',
      favorite: 'Lisa',
    },
    {
      id: 'Steve',
      type: 'hero',
      favorite: 'Jennie',
    },
    {
      id: 'Tony',
      type: 'hero',
      favorite: 'Jisoo',
    },
  ];

  var holder = {};
  const ar = []
  obj.forEach(function (d) {
    if (holder.hasOwnProperty(d.id)) {
      holder[d.id] = ar.push(holder[d.id] + d.favorite);
    } else {
      holder[d.id] = d.favorite;
    }
  });

  var obj2 = [];

  for (var prop in holder) {
    obj2.push({ name: prop, favorite: holder[prop] });
  }

  console.log(obj2);

но выход -

[ { name: 'Tony', favorite: 2 },
  { name: 'Jane', favorite: null },
  { name: 'Steve', favorite: 'Jennie' } ]

Как я могу это сделать?

Ответы [ 6 ]

4 голосов
/ 16 мая 2019

Вы можете сделать это с помощью одного Array.reduce и, скорее всего, это будет наиболее простой и эффективный подход:

var data = [ { id: 'Tony', type: 'hero', favorite: 'Rosie', }, { id: 'Jane', type: 'human', favorite: null, }, { id: 'Tony', type: 'hero', favorite: 'Lisa', }, { id: 'Steve', type: 'hero', favorite: 'Jennie', }, { id: 'Tony', type: 'hero', favorite: 'Jisoo', }, ]

let result = data.reduce((r, {id,type,favorite}) => {
  r[id] = r[id] || {id, type, favorite: []}
  r[id].favorite.push(favorite)
  return r
}, {})

console.log(Object.values(result))

Идея состоит в том, чтобы "группировать по" id и затем продолжать нажимать на массив favorites на каждой итерации.

Для ES5 Вы можете сделать это аналогичным образом:

var data = [ { id: 'Tony', type: 'hero', favorite: 'Rosie', }, { id: 'Jane', type: 'human', favorite: null, }, { id: 'Tony', type: 'hero', favorite: 'Lisa', }, { id: 'Steve', type: 'hero', favorite: 'Jennie', }, { id: 'Tony', type: 'hero', favorite: 'Jisoo', }, ]

let result = data.reduce(function(r, c){
   r[c.id] = r[c.id] || {id: c.id, type: c.type, favorite: []}
   r[c.id].favorite.push(c.favorite)
   return r
}, {})

console.log(Object.values(result))

На самом деле lodash для этого не требуется.

0 голосов
/ 25 мая 2019

С Лодашем:

var data = [ { id: 'Tony', type: 'hero', favorite: 'Rosie', }, { id: 'Jane', type: 'human', favorite: null, }, { id: 'Tony', type: 'hero', favorite: 'Lisa', }, { id: 'Steve', type: 'hero', favorite: 'Jennie', }, { id: 'Tony', type: 'hero', favorite: 'Jisoo', }, ]


var result = _(data).groupBy(a => a.id).map((objs, key) => ({
        'id': key,
        'type': _.head(objs).type,
        'favorite': _.map(objs, 'favorite')
    }))
    .value();

console.log(result);
<script src="https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js"></script>
0 голосов
/ 16 мая 2019

Вы можете использовать Reduce для массива.

const arr = [ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Rosie',
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Lisa',
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: 'Jennie',
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Jisoo',
 },
]
const out = arr.reduce((result, el)=> {
    const id = result.findIndex(e => e.id ===el.id)

    if(id> -1){
        result[id] = {...result[id], favorite: [...result[id].favorite, el.favorite]}
    } else {result.push({...el, favorite: [el.favorite].filter(x => x) })}
    return result
}, [])
console.log(out)
0 голосов
/ 16 мая 2019

Используйте map и Set для получения этого результата.

Сначала мы создаем новый уникальный Set, используя поле id.

Мы запускаем новый новый array из этого и вызовите метод map.

const arr = [ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Rosie',
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Lisa',
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: 'Jennie',
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Jisoo',
 },
];

const masterArr = [...new Set(arr.map((e) => e.id))].map(a => ({
  id: a,
  type: arr.find(x => x.id === a).type,
  favorites: arr.filter(x => x.id === a).map(y => y.favorite)
}));

console.log(masterArr);
0 голосов
/ 16 мая 2019

Просто зациклите массив и создайте новый массив после преобразования атрибута favorite в массив, затем для следующих элементов с таким же идентификатором нажмите на favorite array

let users = [{id: 'Tony', type: 'hero', favorite: 'Rosie',}, {id: 'Jane', type: 'human', favorite: null,}, {id: 'Tony', type: 'hero', favorite: 'Lisa',}, {id: 'Steve', type: 'hero', favorite: 'Jennie',}, {id: 'Tony', type: 'hero', favorite: 'Jisoo',},];

// To combine friends of the same user in an array at property friendNames
let merged = {};
for (let user of users) {
    if (typeof merged[user.id] === 'undefined') {
        user.favorite = [user.favorite];
        merged[user.id] = user;
    } else {
        merged[user.id].favorite.push(user.favorite)
    }
}

console.log(Object.values(merged));
0 голосов
/ 16 мая 2019

Сгруппируйте по id с _.group(), а затем объедините каждую группу, используя _.map() и _.mergeWith(), и соберите favorite в массив:

const data = [{"id":"Tony","type":"hero","favorite":"Rosie"},{"id":"Jane","type":"human","favorite":null},{"id":"Tony","type":"hero","favorite":"Lisa"},{"id":"Steve","type":"hero","favorite":"Jennie"},{"id":"Tony","type":"hero","favorite":"Jisoo"}]

const result = _(data)
  .groupBy('id')
  .map(g => _.mergeWith({}, ...g, (o, s, k) => {
    if(k !== 'favorite') return // non favorite key are not collected to an array
    
    if(_.isNil(s)) return o // don't add null or undefined to array
    
    return [].concat(o || [], s) // concat other values to array
  }))
  .value()
  
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
...