Как лучше всего уменьшить и объединить коллекцию объектов - PullRequest
2 голосов
/ 05 августа 2020

Итак, на этой неделе я столкнулся с дилеммой, пытаясь решить то, что казалось простой проблемой, но я ошибался.

Пример кода:

let arr = [
  { id: 'ae0123', cost: 100.00, orders: 5 },
  { id: 'ae0123', cost: 50.00, orders: 5 },
  { id: 'ae4321', cost: 75.00, orders: 1 }
]

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

Есть предложения?

Конечный результат будет выглядеть примерно так:

[
  { id: 'ae0123', cost: 150.00, orders: 10 },
  { id: 'ae4321', cost: 75.00, orders: 1 }
]

Конечно, настоящее приложение не будет иметь статически типизированных идентификаторов, но они были записаны в этом примере. Пожалуйста, примите это во внимание.

Заранее спасибо!

Ответы [ 7 ]

1 голос
/ 05 августа 2020

Вы можете взять объект для группировки и массив для добавления желаемых свойств.

let array = [{ id: 'ae0123', cost: 100.00, orders: 5 }, { id: 'ae0123', cost: 50.00, orders: 5 }, { id: 'ae4321', cost: 75.00, orders: 1 }],
    result = Object.values(array.reduce((r, o) => {
        if (r[o.id]) {
            ['cost', 'orders'].forEach(k => r[o.id][k] += o[k]);
        } else {       
            r[o.id] = { ...o };
        }
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 05 августа 2020

Вы можете использовать Map для хранения объектов по id и добавлять значения, если они уже существуют в нем:

let arr = [
  { id: 'ae0123', cost: 100.00, orders: 5 },
  { id: 'ae0123', cost: 50.00, orders: 5 },
  { id: 'ae4321', cost: 75.00, orders: 1 }
];
let map = {};
for(let i = 0; i < arr.length; i++){
     let item = arr[i];
     if(map[item.id]){
          map[item.id].cost += item.cost;
          map[item.id].orders += item.orders;
     }else{
          map[item.id] = item;
     }
}
console.log(Object.values(map));
0 голосов
/ 05 августа 2020
let newArr = []

arr.forEach((el, ind) => { 
    let uniqueId = el.id;
    let obj = el;
    let multiple = false;
    arr.forEach((e, i) => {
        if(e.id == uniqueId && ind != i ) {
            el.cost += e.cost;
            el.orders += e.orders;
             multiple = true;
             arr.splice(i,1);
             newArr.push(el)
        }
    });

    if(!multiple){
        newArr.push(obj);
    }

});

Скажите, если это сработает, это создаст новый массив с объектами.

0 голосов
/ 05 августа 2020

Наверное, это то, что вы хотите

let arr = [
  { id: 'ae0123', cost: 100.00, orders: 5 },
  { id: 'ae0123', cost: 50.00, orders: 5 },
  { id: 'ae4321', cost: 75.00, orders: 1 }
]

let uniq = []
arr.map(x => {
  if(!uniq.includes(x.id)) uniq = [...uniq, x.id]
})

uniq = uniq.map(x => {
  let filtered = arr.filter(y => y.id === x)
  let res = filtered.shift()
  for(const z of filtered) {
    const {cost, orders} = z
    res.cost += cost
    res.orders += orders
  }
  return res
})

console.log(uniq)
0 голосов
/ 05 августа 2020

Я бы go с помощью метода reduce объекта Array, вышеупомянутое решение с использованием буквального объекта также работает, но я думаю, что для такого случая reduce создает код более читабельный и элегантный:

const arr = [
  { id: 'ae0123', cost: 100.00, orders: 5 },
  { id: 'ae0123', cost: 50.00, orders: 5 },
  { id: 'ae4321', cost: 75.00, orders: 1 }
];

const newArr = arr.reduce((acc, obj) => {
  if (!acc[obj.id]) {
    acc[obj.id] = obj;
  } else {
    acc[obj.id].cost += obj.cost;
    acc[obj.id].orders += obj.orders;
  }
  
  return acc;
}, {});

console.log( Object.values(newArr) );
0 голосов
/ 05 августа 2020

let arr = [
  { id: 'ae0123', cost: 100.00, orders: 5 },
  { id: 'ae0123', cost: 50.00, orders: 5 },
  { id: 'ae4321', cost: 75.00, orders: 1 }
]

let obj={};

arr.forEach(item=>{
  if(obj[item.id]){
    obj[item.id].cost +=item.cost;
    obj[item.id].orders +=item.orders;
  }
  else{
    obj[item.id]=item;
  }
});

const mappedArr=Object.keys(obj).map(key=>obj[key]);

console.log(mappedArr)

Попробуйте это

0 голосов
/ 05 августа 2020

Создайте новый массив

Для каждого элемента, если он уже существует, добавьте стоимость и заказы, иначе добавьте его в массив.

let arr = [
  { id: 'ae0123', cost: 100.00, orders: 5 },
  { id: 'ae0123', cost: 50.00, orders: 5 },
  { id: 'ae4321', cost: 75.00, orders: 1 }
]

let newArr = []

arr.forEach(item => {
  let existingItem = newArr.find(x => x.id == item.id);
  if (existingItem != undefined) {
    existingItem.cost += item.cost;
    existingItem.orders += item.orders;
  } else {
    newArr.push(item);
  }
});

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