Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

125
Visualizações
How to combine all objects into one based on key

Here is the scenario I am looking at:

I want to reduce these objects

const data = [
  {
    id: 1,
    totalAmount: 1500,
    date: '2021-01-01',
    vendor_id: 2,
    totalTransaction: 12,
    isRefund: false,
  },
  {
    id: 2,
    totalAmount: 200,
    date: '2021-01-01',
    vendor_id: 2,
    totalTransaction: 2,
    isRefund: true,
  },
  {
    id: 3,
    totalAmount: 200,
    date: '2021-01-01',
    vendor_id: 2,
    totalTransaction: 1,
    isRefund: true,
  },
];

and I found a solution that adds their values:

const deepMergeSum = (obj1, obj2) => {
  return Object.keys(obj1).reduce((acc, key) => {
    if (typeof obj2[key] === 'object') {
      acc[key] = deepMergeSum(obj1[key], obj2[key]);
    } else if (obj2.hasOwnProperty(key) && !isNaN(parseFloat(obj2[key]))) {
      acc[key] = obj1[key] + obj2[key]
    }
    return acc;
  }, {});
};

const result = data.reduce((acc, obj) => (acc = deepMergeSum(acc, obj)));
const array = []
const newArray = [...array, result]

which results to:

const newArray = [
 {
   id: 6,
   totalAmount: 1900,
   date: '2021-01-012021-01-012021-01-01',
   vendor_id: 6,
   totalTransaction: 15
 }
]

And now my problem is I don't know yet how to work this around to have my expected output which if isRefund is true, it must be subtracted instead of being added, retain the vendor_id and also the concatenated date instead of only one entry date:

const newArray = [
 {
   id: 1(generate new id if possible),
   totalAmount: 1100,
   date: '2021-01-01',
   vendor_id: 2,
   totalTransaction: 15,
   isRefund: null(this can be removed if not applicable),
 },
];

I will accept and try to understand any better way or workaround for this. Thank you very much.

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

As you want custom behaviour for several fields, and don't need the recursive aspect of the merge, I would suggest you create a custom merge function, specific to your business logic:

const data = [{id: 1,totalAmount: 1500,date: '2021-01-01',vendor_id: 2,totalTransaction: 12,isRefund: false,},{id: 2,totalAmount: 200,date: '2021-01-01',vendor_id: 2,totalTransaction: 2,isRefund: true,},{id: 3,totalAmount: 200,date: '2021-01-01',vendor_id: 2,totalTransaction: 1,isRefund: true,},];

function customMerge(a, b) {
    if (a.vendor_id !== b.vendor_id || a.date !== b.date) {
        throw "Both date and vendor_id must be the same";
    }
    return {
        id: Math.max(a.id, b.id),
        totalAmount: (a.isRefund ? -a.totalAmount : a.totalAmount) 
                   + (b.isRefund ? -b.totalAmount : b.totalAmount),
        date: a.date,
        vendor_id: a.vendor_id,
        totalTransaction: a.totalTransaction + b.totalTransaction
    };
}

const result = data.reduce(customMerge);
if (data.length > 1) result.id++; // Make id unique
console.log(result);

You could also reintroduce the isRefund property in the result for when the total amount turns out to be negative (only do this when data.length > 1 as otherwise result is just the original single object in data):

result.isRefund = result.totalAmount < 0;
result.totalAmount = Math.abs(result.totalAmount);

Distinct results for different dates and/or vendors

Then use a "dictionary" (plain object or Map) keyed by date/vendor combinations, each having an aggregating object as value.

To demonstrate, I added one more object in the data that has a different date and amount of 300:

const data = [{id: 1,totalAmount: 1500,date: '2021-01-01',vendor_id: 2,totalTransaction: 12,isRefund: false,},{id: 2,totalAmount: 200,date: '2021-01-01',vendor_id: 2,totalTransaction: 2,isRefund: true,},{id: 3,totalAmount: 200,date: '2021-01-01',vendor_id: 2,totalTransaction: 1,isRefund: true,},{id: 4,totalAmount: 300,date: '2021-01-02',vendor_id: 2,totalTransaction: 1,isRefund: false,}];

function customMerge(acc, {id, date, vendor_id, totalAmount, totalTransaction, isRefund}) {
    let key = date + "_" + vendor_id;
    if (!(id <= acc.id)) acc.id = id;
    acc[key] ??= {
        date,
        vendor_id,
        totalAmount: 0,
        totalTransaction: 0
    };
    acc[key].totalAmount += isRefund ? -totalAmount : totalAmount;
    acc[key].totalTransaction += totalTransaction;
    return acc;
}

let {id, ...grouped} = data.reduce(customMerge, {});
let result = Object.values(grouped).map(item => Object.assign(item, { id: ++id }));
console.log(result);

about 4 years ago · Juan Pablo Isaza Relatório

0

it could be help, if you are looking for the same output, can add other checklist based on your requirement, for filtered date, logic would be little different but the output will be same.

const getTotalTranscation = () =>
  transctionLists.reduce((prev, current) => {
    const totalAmount = current.isRefund
      ? prev.totalAmount - current.totalAmount
      : prev.totalAmount + current.totalAmount;

    const totalTransaction = current.isRefund
      ? prev.totalTransaction - current.totalTransaction
      : prev.totalTransaction + current.totalTransaction;

    return {
      ...current,
      id: current.id + 1,
      totalAmount,
      totalTransaction,
      isRefund: totalAmount < 0,
    };
  });
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda