Reputation: 13
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
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
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