const data = [
{
product_id: 1245,
product_name: "XYZ",
price: "10.00",
batch_number: 1,
},
{
product_id: 12456,
product_name: "RST",
price: "10.00",
batch_number: 1,
},
{
product_id: 111,
product_name: "LMN",
price: "10.00",
batch_number: 2,
},
{
product_id: 222,
product_name: "PQR",
price: "10.00",
batch_number: 2,
},
{
product_id: 456,
product_name: "KKK",
price: "10.00",
batch_number: null,
},
];
i want to format this object into an this type with add same batch number product in to product id and product name and price as combained. Is there any way to cahnge this. How do cahnge this to that expectedoutput Expected output
const output = [
{
product_id: "1245, 12345",
product_name: "XYZ, RST",
price: "20.00",
batch_number: 1,
},
{
product_id: "111, 222",
product_name: "LMN, PQR",
price: "20.00",
batch_number: 2,
},
{
product_id: 456,
product_name: "KKK",
price: "10.00",
batch_number: null,
},
];
CodePudding user response:
- Group
data
array bybatch_number
property, store in a Map object holds key-value pairs.
const map = new Map(data.map(obj=>[obj.batch_number,[]]))
for (let obj of data) {
map.set(obj.batch_number, [...map.get(obj.batch_number)??[],obj]);
}
/*
{1 => [
{
"product_id": 1245,
"product_name": "XYZ",
"price": "10.00",
"batch_number": 1
},
{
"product_id": 12456,
"product_name": "RST",
"price": "10.00",
"batch_number": 1
}
], 2 => Array(2), null => ...}
*/
- Loop over each obj in map entries() method returns a new iterator object that contains the [key, value] pairs for each element in the Map object.
for (let [batch, objs] of map.entries())
- Each iteration initializes an
object
with abatch_number
property! and each group ofbatch_number
gets their product_id, product_name and price accumulates the price to store them in variables arrValsIds, arrValsNames, prices respectively.
const object = {
product_id: "",
product_name: "",
price: "",
batch_number: batch,
}
const arrValsIds = [];
const arrValsNames = [];
let prices = 0;
for (let obj of objs) {
arrValsIds.push(obj.product_id);
arrValsNames.push(obj.product_name);
prices = Number(obj.price);
}
- Last not but least, push to an array object with properties
product_id
,product_name
joined by', '
andtotalPrice
withtoFixed()
method which formats a number using fixed-point notation.
output.push({
product_id: arrValsIds.join(", "),
product_name: arrValsNames.join(", "),
price: prices.toFixed(2).toString(),
batch_number: batch,
})
Expected output:
const data = JSON.parse('[{"product_id":1245,"product_name":"XYZ","price":"10.00","batch_number":1},{"product_id":12456,"product_name":"RST","price":"10.00","batch_number":1},{"product_id":111,"product_name":"LMN","price":"10.00","batch_number":2},{"product_id":222,"product_name":"PQR","price":"10.00","batch_number":2},{"product_id":456,"product_name":"KKK","price":"10.00","batch_number":null}]');
const map = new Map(data.map(obj=>[obj.batch_number,[]]))
for (let obj of data) {
map.set(obj.batch_number, [...map.get(obj.batch_number)??[],obj]);
}
const output = [];
for (let [batch, objs] of map.entries()) {
const object = {
product_id: "",
product_name: "",
price: "",
batch_number: batch,
}
const arrValsIds = [];
const arrValsNames = [];
let totalPrice = 0;
for (let obj of objs) {
arrValsIds.push(obj.product_id);
arrValsNames.push(obj.product_name);
totalPrice = Number(obj.price);
}
output.push({
product_id: arrValsIds.join(", "),
product_name: arrValsNames.join(", "),
price: totalPrice.toFixed(2).toString(),
batch_number: batch,
})
}
console.log(output);
CodePudding user response:
The snippet below first categorizes the products by batch_id
. Then it combines the data of all the products in each batch_id
. See comments.
const data = [{
product_id: 1245,
product_name: "XYZ",
price: "10.00",
batch_number: 1,
},
{
product_id: 12456,
product_name: "RST",
price: "10.00",
batch_number: 1,
},
{
product_id: 111,
product_name: "LMN",
price: "10.00",
batch_number: 2,
},
{
product_id: 222,
product_name: "PQR",
price: "10.00",
batch_number: 2,
},
{
product_id: 456,
product_name: "KKK",
price: "10.00",
batch_number: null,
},
];
// This is a helper function that creates a key on the map if it doesn't exist
const mapGetOrSet = (map, key, getValue) => {
if (map.has(key)) return map.get(key)
const value = getValue()
map.set(key, value)
return value
}
const transform = data => {
// Use a Map
const productsByBatch = new Map()
// Put each product into a batch
data.forEach(obj => {
const products = mapGetOrSet(productsByBatch, obj.batch_number, () => [])
products.push(obj)
})
// Transform the map into the format the question wants
return [...productsByBatch].map(([batchNumber, products]) => ({
batch_number: batchNumber,
// Get the product_id of all products in the batch and turn them into 1 comma seperated string using Array.prototype.join()
product_id: products.map(({ product_id }) => product_id).join(),
// Same thing as id
product_name: products.map(({ product_name }) => product_name).join(),
price: products
// Turn string into number for addition
.map(({ price }) => parseFloat(price))
// Add every price
.reduce((total, productPrice) => total productPrice)
}))
}
console.log(transform(data))
The only difference from the output format is that price
is a number
instead of "25.00"
.
CodePudding user response:
Presented below is one possible way (using ".reduce()"
) to achieve the desired objective.
Code Snippet
const groupByBatch = arr => (
Object.values( // extract the "values" array from intermediate result obj
arr.reduce( // use ".reduce()" to iterate thru the data
(acc, obj) => { // "acc" is the accumulator / aggregator
// check if batch_number already present in "acc"
let currObj = acc[obj.batch_number] ?? false;
// if found, concat "obj" props to existing ones (ie, "currObj" props)
// else, simply populate "acc" with "obj" props
acc[obj.batch_number] = currObj
? {
product_id: `${currObj.product_id.toString()}, ${obj.product_id.toString()}`,
product_name: `${currObj.product_name}, ${obj.product_name}`,
price: ( currObj.price obj.price).toString(),
batch_number: obj.batch_number
} : {
product_id: obj.product_id.toString(),
product_name: obj.product_name,
price: obj.price,
batch_number: obj.batch_number
};
return acc; // return the accumulator/aggregator "acc"
},
{} // initialize "acc" to empty-object
)
)
);
const data = [{
product_id: 1245,
product_name: "XYZ",
price: "10.00",
batch_number: 1,
},
{
product_id: 12456,
product_name: "RST",
price: "10.00",
batch_number: 1,
},
{
product_id: 111,
product_name: "LMN",
price: "10.00",
batch_number: 2,
},
{
product_id: 222,
product_name: "PQR",
price: "10.00",
batch_number: 2,
},
{
product_id: 456,
product_name: "KKK",
price: "10.00",
batch_number: null,
},
];
console.log('group data by batch: ', groupByBatch(data));
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.