Объединять объекты с одинаковым идентификатором в массиве - PullRequest
3 голосов
/ 04 ноября 2019

Полагаю, у меня простая мертвая проблема, но я так и не нашел решения. У меня есть массив, который выглядит следующим образом:

var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}]

Я хотел бы изменить его так, чтобы он выглядел так (объединить по идентификатору и соединить элементы):

newArray = [{
  id: 1,
  elements: [1, 2, 3, 4]
}, {
  id: 5,
  elements: ['a', 'b', 'c', 'd']
}, {
  id: 27,
  elements: []
}]

У меня уже былонесколько попыток, но все еще не нашли элегантный способ сделать это.

Ответы [ 7 ]

4 голосов
/ 04 ноября 2019

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

var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}];

const arrayHashmap = originalArray.reduce((obj, item) => {
  obj[item.id] ? obj[item.id].elements.push(...item.elements) : (obj[item.id] = { ...item });
  return obj;
}, {});

const mergedArray = Object.values(arrayHashmap);

console.log(mergedArray);
1 голос
/ 04 ноября 2019

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

var data = [{"id":1,"elements":[1,2]},{"id":1,"elements":[3,4]},{"id":5,"elements":["a","b"]},{"id":5,"elements":["c","d"]},{"id":27,"elements":[]}]

const result = data.reduce((r, {id, elements}) => {
  if(r.get(id)) r.get(id).elements.push(...elements);
  else r.set(id, {id, elements});
  return r;
}, new Map).values();

console.log([...result])
1 голос
/ 04 ноября 2019

Это будет работать, а также прилично легко понять. Во-первых, мы проверяем, есть ли идентификатор в newArray или нет, и сохраняем память об этом через логическое значение вне цикла, которое мы можем проверить позже. После этого, если идентификатор «пробел» пуст, мы его заполним, если нет, то там уже есть идентификатор. Поэтому нам нужно обновить их элементы. Мы можем сделать это, во-первых, захватывая объект в новом массиве, который соответствует дублирующему объекту в исходном массиве с тем же идентификатором. После этого мы просто помещаем каждый элемент из дубликата в новый.


<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}]

var newArray = [];
for (obj of originalArray) {

    var empty = true;
    for (newobj of newArray) {
       if (obj.id == newobj.id) { empty = false; }
    }
    if (empty) {
        newArray.push({id: obj.id, elements: obj.elements});
    } else {
        for (newobj of newArray) {
           if (newobj.id == obj.id) {
               for (o of obj.elements) {
                 newobj.elements.push(o);
                }
           }
        }
    }
}
console.log(newArray);
1 голос
/ 04 ноября 2019

Вы можете использовать Array.prototype.reduce () для создания объекта с идентификаторами в качестве свойств и Object.values ​​() для получения результата:

const originalArray = [{id: 1, elements: [1, 2]}, {id: 1, elements: [3, 4]}, {id: 5, elements: ['a', 'b']}, {id: 5, elements: ['c', 'd']}, {id: 27, elements: []}]
const objIds = originalArray.reduce((a, { id, elements }) => {
  a[id] = a[id] || {id, elements: []}
  return {...a, ...{[id]: {id, elements: a[id].elements.concat(elements)}}}
}, {})
const result = Object.values(objIds)

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 04 ноября 2019

Вы можете сделать это с помощью функции уменьшения:

[{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}].reduce((prev, cur) => {
    const index = prev.findIndex(v => v.id === cur.id);
    if (index === -1) {
       prev.push(cur);
    } else {
        prev[index].elements.push(...cur.elements);
    }
    return prev;
}, [])
1 голос
/ 04 ноября 2019

Попробуйте этот код:

var originalArray = [{
      id: 1,
      elements: [1, 2]
    },
    {
      id: 1,
      elements: [3, 4]
    },
    {
      id: 5,
      elements: ['a', 'b']
    },
    {
      id: 5,
      elements: ['c', 'd']
    }, {
      id: 27,
      elements: []
    }]
    var newArray = [];
    originalArray.forEach(item => {
       var newItem = {id: item.id, elements: []};
       originalArray.forEach(innerItem => {
          if(innerItem.id == item.id){
              newItem.elements = newItem.elements.concat(innerItem.elements);
          }
       });
      newArray.push(newItem);
    });
    console.log(newArray);

Вывод:

[{
  id: 1,
  elements: [1, 2, 3, 4]
}, {
  id: 5,
  elements: ['a', 'b', 'c', 'd']
}, {
  id: 27,
  elements: []
}]
0 голосов
/ 04 ноября 2019

Вы можете использовать для этого вложенные циклы.

var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}]


for(let i=0;i<originalArray.length;i++){
  let key = originalArray[i].id;
  for(let j=i+1;j<originalArray.length;j++){
    if(originalArray[j].id == key){
      originalArray[i].elements  = [...originalArray[i].elements,...originalArray[j].elements];
      delete originalArray.splice(j,1);
    }

  }
}

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