FreshCeviche
FreshCeviche

Reputation: 13

Remove duplicate keys and combine unique values in JavaScript array

I have an array containing a customer ID, value of transaction, and transaction ID for each transaction performed by the customer.

I have 20,000 transactions performed by 9,000 customers. I want one customer ID, an array of all the prices per that customer ID, and an array of all the transaction Ids per customer ID.

Currently looks like this:

var transactionArray =
{
  customerId: '1',
  price: [ 100 ],
  transactionID: ['00a13']
},
{
  customerId: '2',
  price: [ 200 ],
  transactionID: ['00a14']
},
{
  customerId: '1',
  price: [ 700 ],
  transactionID: ['00a15']
},
{
  customerId: '2',
  price: [ 1700 ],
  transactionID: ['00a16']
},

... 19996 more items

and I'd like it to look like this:

var customerArray =

{
  customerId: '1',
  price: [ 100, 700 ],
  transactionID: ['00a13', '00a15']
},
{
  customerId: '2',
  price: [ 200, 1700 ],
  transactionID: ['00a14', '00a16']
},

...8998 more items

Upvotes: 1

Views: 511

Answers (2)

epascarello
epascarello

Reputation: 207511

Just using reduce and push the elements onto the array

var transactionArray = [{
    customerId: '1',
    price: [100],
    transactionID: ['00a13']
  },
  {
    customerId: '2',
    price: [200],
    transactionID: ['00a14']
  },
  {
    customerId: '1',
    price: [700],
    transactionID: ['00a15']
  },
  {
    customerId: '2',
    price: [1700],
    transactionID: ['00a16']
  },
]

var results = Object.values(transactionArray.reduce((custs, { customerId, price, transactionID }) => {
  var customer = custs[customerId]
  if (!customer) {
    custs[customerId] = {
      customerId: customerId,
      price: [...price],
      transactionID: [...transactionID]
    }
  } else {
    customer.price = [...customer.price, ...price]
    customer.transactionID =  [...customer.transactionID, ...transactionID]
  }

  return custs
}, {}))

console.log(results)

Upvotes: 1

sbolel
sbolel

Reputation: 3526

It's convenient that customerId's are integers. If that ever changes, then you will need to index them, then rebuild the object.

// create a separate array for holding order of customerIds
const customerIds = []

const result = transactionArray
  .reduce((acc, { customerId, price, transactionID }) => {
    const idIndex = customerIds.indexOf(customerId)
    // check if customerId exists in customerIds array
    if (idIndex < 0) {
      // if it doesn't, add it to the customerId's array
      customerIds.push(customerId)
      // then add the matching price and transactionID to the accumulator
      // of this reduce, spreading the contents of the array into 2 new arrays.
      acc.push([[...price], [...transactionID]])
    } else {
      // if the customerId is already accounted for, then
      // add the price and transactionID to that customer's bucket
      // at the same index where the customerId exists inside customerIds
      acc[idIndex][0].push(...price)
      acc[idIndex][1].push(...transactionID)
    }
    return acc
  }, [])
  // finally, convert the arrays back into objects
  .map((value, index) => {
    return ({ 
      customerId: customerIds[index],
      price: value[0],
      transactionID: value[1],
    })
  })


console.log(result)

which logs:

[
  {
    customerId: '1',
    price: [ 100, 700 ],
    transactionID: [ '00a13', '00a15' ]
  },
  {
    customerId: '2',
    price: [ 200, 1700 ],
    transactionID: [ '00a14', '00a16' ]
  }
]

If the customerIds were strings that didn't represent integers, this will still work -- for example, if your customer data looked like this:

const transactionArray = [
  {
    customerId: '324asdrea',
    price: [ 100 ],
    transactionID: ['00a13']
  },
  {
    customerId: '4hdffgi2',
    price: [ 200 ],
    transactionID: ['00a14']
  },
  {
    customerId: '324asdrea',
    price: [ 700 ],
    transactionID: ['00a15']
  },
  {
    customerId: '4hdffgi2',
    price: [ 1700 ],
    transactionID: ['00a16']
  }
]

which results in:

[
  {
    customerId: '324asdrea',
    price: [ 100, 700 ],
    transactionID: [ '00a13', '00a15' ]
  },
  {
    customerId: '4hdffgi2',
    price: [ 200, 1700 ],
    transactionID: [ '00a14', '00a16' ]
  }
]

Upvotes: 0

Related Questions