I am having an array like,
var result = [
{
"sItem" : [
"Pizza Margherita","Pizza marinara"
],
"sImage" : [
"https://assets.marthastewart.com/styles/wmax-300/d31/pizza-margherita-0606-mla102155/pizza-margherita-0606-mla102155_vert.jpg","https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"
],
"nQuantity" : 1,
"eDeliveryStatus" : "n",
"nPrice" : 215,
"sReceiptId" : "pRjZpGzIDPpX",
}
];
wants to make Object like, I am running a loop through title array pushing data.
[
{
"title":"Pizza Margherita",
"subtitle":"Pizza Margherita",
"quantity":1,
"price":215,
"currency":"INR",
"image_url":"https://images.mcdelivery.co.in/hardcastle-restaurants-pvt-ltd/image/upload/q_auto:low,fl_lossy,w_300/v1484907263/Items/2754.png"
},
{
"title":"Pizza marinara",
"subtitle":"Pizza marinara",
"quantity":1,
"price":215,
"currency":"INR",
"image_url":"https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"
}
]
and this is how i am trying but failing :(,
result.forEach(el => {
el.sItem.forEach(el2 => {
elementRec.push({
"title": el2,
"subtitle": el2,
"quantity": el.nQuantity,
"price": el.nPrice,
"currency": "INR",
"image_url": el.sImage
})
});
})
I know this is wrong but new to Javascript.
You are almost there.
In you forEach, add an index parameter and use it to retrieve the right image from the sImage array :
el.sItem.forEach((el2, index) => {
elementRec.push({
"title": el2,
"subtitle": el2,
"quantity": el.nQuantity,
"price": el.nPrice,
"currency": "INR",
"image_url": el.sImage[index]
})
});
var result = [
{
"sItem" : [
"Pizza Margherita",
"Pizza marinara"
],
"sImage" : [
"https://assets.marthastewart.com/styles/wmax-300/d31/pizza-margherita-0606-mla102155/pizza-margherita-0606-mla102155_vert.jpg",
"https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"
],
"nQuantity" : 1,
"eDeliveryStatus" : "n",
"nPrice" : 215,
"sReceiptId" : "pRjZpGzIDPpX",
}
];
var elementRec = [];
result.forEach(el => {
el.sItem.forEach((el2, index) => {
elementRec.push({
"title": el2,
"subtitle": el2,
"quantity": el.nQuantity,
"price": el.nPrice,
"currency": "INR",
"image_url": el.sImage[index]
})
});
});
console.log(elementRec);
You could map the inner sItem and corresponding sImage to new object by some destruction and short properties.
var data = [{ sItem: ["Pizza Margherita", "Pizza marinara"], sImage: ["https://assets.marthastewart.com/styles/wmax-300/d31/pizza-margherita-0606-mla102155/pizza-margherita-0606-mla102155_vert.jpg", "https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"], nQuantity: 1, eDeliveryStatus: "n", nPrice: 215, sReceiptId: "pRjZpGzIDPpX" }],
result = data.reduce((r, { sItem, sImage, nQuantity: quantity, nPrice: price }) =>
r.concat(sItem.map((title, i) => ({
title, subTitle: title, quantity, price, currency: 'INR', image_url: sImage[i]
}))),
[]
);
console.log(result);
I think you are trying to do something like this. First create a new array. I'll call it converted. Then push the result objects into it with .forEach() like this.
var converted = [];
result.forEach(function(i){
converted.push({
"title": i.sItem[0],
"subtitle": i.sItem[0],
"quantity": i.nQuantity,
"price": i.nPrice,
"currency": "INR",
"image_url": i.sImage[0]
});
})
Try this fiddle
Related
Hi,
I have one array of objects with all items and their respective price like this:
var items = [
{
"id": "001",
"name": "apple",
"price": 500
},
{
"id": "002",
"name": "banana",
"price": 700
},
{
"id": "003",
"name": "pear",
"price": 200
}
];
then I have a client's car like this:
var cart = [{
"id": "001",
"qty": 2
},
{
"id": "002",
"qty": 3
},
{
"id": "003",
"qty": 4
}
];
client's credit is stored in a variable. I want to check the second array against the first one to get the total of the cart and make sure it wont exceed client's credit. Im not sure how to do it though. I tried:
var mytotal=cart.map(d => {
var total=0;
items.forEach(rm => {
total = total+(d.qty*rm.price);
} return total;
});
if(credit >= total) {//dosomething}
but it didnt work. What is the right approach?
Thank you.
You can divide your problem into two tasks: join and sum.
Join
const joined = items.map(item => ({...item, ...cart.find(c => c.id === item.id)}));
Note that in case the id won't match, find will return null, and the spread (...) will result in no change to the object
Sum
const sum = joined.reduce((sum, curr) => sum += curr.price * curr.qty, 0);
A safer version would be:
const sum = joined.reduce((sum, curr) => sum += (curr.price ?? 0) * (curr.qty ?? 0), 0);
var items = [
{
"id": "001",
"name": "apple",
"price": 500
},
{
"id": "002",
"name": "banana",
"price": 700
},
{
"id": "003",
"name": "pear",
"price": 200
}
];
var cart = [{
"id": "001",
"qty": 2
},
{
"id": "002",
"qty": 3
},
{
"id": "003",
"qty": 4
}
];
const joined = items.map(item => ({...item, ...cart.find(c => c.id === item.id)}));
const sum = joined.reduce((sum, curr) => sum += curr.price * curr.qty, 0);
console.log(`joined object is: `, joined);
console.log(`sum is: ${sum}`);
I am a little late in the game, but maybe the following snippet is still of interest? It picks up the idea of creating a lookup object itms and for each shopping cart entry it also combines two objects into a new one with a subtotal subt, so you can easliy create a meaningfull shopping cart table. The variable ttl is updated alongside and contains the total sum:
const items = [
{
"id": "001",
"name": "apple",
"price": 500
},
{
"id": "002",
"name": "banana",
"price": 700
},
{
"id": "003",
"name": "pear",
"price": 200
}
],
cart = [{
"id": "001",
"qty": 2
},
{
"id": "002",
"qty": 3
},
{
"id": "003",
"qty": 4
}
];
// Turn the items array into an object, facilitating a fast lookup:
const itms=items.reduce((a,c)=>(a[c.id]=c,a),{});
let ttl=0;
// calculate the totals:
const res=cart.map(c=>{
const p=itms[c.id], subt=c.qty*p.price;
ttl+=subt;
return {...c,...p,subt}
})
// Show the result:
console.log(res,ttl);
To implement a reusable and efficient solution you can create a lookup table on the items array, here using a Map, which allows you to directly access the item by id.
const itemLookup = new Map(items.map((item) => [item.id, item]))
// Map(3) {
// '001' => { id: '001', name: 'apple', price: 500 },
// '002' => { id: '002', name: 'banana', price: 700 },
// '003' => { id: '003', name: 'pear', price: 200 }
// }
You can then create a getCartTotal helper which will use the lookup table to total the cart passed to it. (Here we are assuming that any item that will be in the cart will also be in the items array, but for safety you could add optional chaining, t += (itemLookup.get(id)?.price ?? 0) * qty)
const getCartTotal = (cart) => {
return cart.reduce((t, { id, qty }) => (
t += itemLookup.get(id).price * qty
), 0);
}
The result allows you to efficiently re-sum the cart whenever it changes.
const items = [{ "id": "001", "name": "apple", "price": 500 }, { "id": "002", "name": "banana", "price": 700 }, { "id": "003", "name": "pear", "price": 200 }];
const itemLookup = new Map(items.map(({ id, ...item }) => [id, { id, ...item }]));
const getCartTotal = (cart) => {
return cart.reduce((total, { id, qty }) => (
total += itemLookup.get(id).price * qty
), 0);
}
const cart = [{ "id": "001", "qty": 2 }, { "id": "002", "qty": 3 }, { "id": "003", "qty": 4 }];
console.log(getCartTotal(cart)); // 3900
cart[0].qty += 2;
console.log(getCartTotal(cart)); // 4900
In your attempt, you're applying the map function to the cart array. Map applies the function to each element of the array, and returns the new array. The function total = 0 etc is being applied for each element separately.
In the map/reduce way of working, try getting the proper price of each cart element first with map, and then summarize using reduce.
Map/reduce is just one of many ways to solve this issue, you could also do it iteratively with a for loop like you were trying within your map function.
I wanted to list all the products in the database and all the images, today each product can have several images and this way I did it, it returns 1 product object for each image
I tried to do this, but I didn't get what I expected as I said above
async getAllProductAndImages() {
const productsDatabase = await client.query(`
SELECT
products.*,
products_images.id AS imageId,
products_images.name AS imageName,
products_images.product_id AS productImgId
FROM products INNER JOIN products_images
ON products.id = products_images.product_id`)
const products = productsDatabase.rows.map(products => {
const urlImage = `${process.env.APP_API_URL}/files/${products.imagename}`
const productImage = new ProductImage(products.imagename, products.id)
productImage.id = products.imageid
productImage.url = urlImage
const product = new Product(
products.name,
products.description,
products.price,
products.amount
)
product.id = products.id
product.productsImages = productImage
return product
})
return products
}
productsDatabase.rows return
[
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"imageid": "78eb77d4-bf5a-44c1-a37a-0a28eb0f85ad",
"imagename": "21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg"
},
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"imageid": "2157284b-34fd-41a4-ac3e-aa4d3f46b883",
"imagename": "96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg"
}
]
return that I have using the code above
[
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"productsImages": {
"id": "78eb77d4-bf5a-44c1-a37a-0a28eb0f85ad",
"name": "21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
"url": "http://localhost:3000/files/21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
"product_id": "3f671bc1-5163-44c8-88c9-4430d45f1471"
}
},
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"productsImages": {
"id": "2157284b-34fd-41a4-ac3e-aa4d3f46b883",
"name": "96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg",
"url": "http://localhost:3000/files/96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg",
"product_id": "3f671bc1-5163-44c8-88c9-4430d45f1471"
}
]
this is the return I expect and maybe there will be more stuff inside the productImages array there in the future
[
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"productImages": [
{
"url": "http://localhost:3000/files/21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
"url": "http://localhost:3000/files/96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg"
}
]
}
]
Here is the solution considering productsDatabase.rows as arr:
const arr = [
{
id: "3f671bc1-5163-44c8-88c9-4430d45f1471",
name: "a",
description: "a",
price: "10",
amount: 5,
imageid: "78eb77d4-bf5a-44c1-a37a-0a28eb0f85ad",
imagename:
"21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
},
{
id: "3f671bc1-5163-44c8-88c9-4430d45f1471",
name: "a",
description: "a",
price: "10",
amount: 5,
imageid: "2157284b-34fd-41a4-ac3e-aa4d3f46b883",
imagename:
"96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg",
},
];
const newArr = [];
arr.forEach(a => {
if (!newArr.find(na => na.id === a.id)) {
const data = arr.filter(i => i.id === a.id).map(j => {
return {
url: `${process.env.APP_API_URL ? process.env.APP_API_URL : 'http://localhost:3000/'}files/${j.imagename}`
}});
newArr.push({
id: a.id,
name: a.name,
description: a.description,
amount: a.amount,
productsImages: data,
})
}
});
console.log(newArr);
You can just process the array to build a nested structure, but it might be easier to start with a subquery:
async getAllProductAndImages() {
const {rows} = await client.query(`
SELECT products.*, (
SELECT json_agg(json_build_object(
'id', products_images.id,
'name', products_images.name
))
FROM products_images
WHERE products_images.product_id = products.id;
) AS images
FROM products;
`);
const products = rows.map(row => {
const product = new Product(
row.name,
row.description,
row.price,
row.amount
);
product.id = row.id;
product.productsImages = row.images.map(img => {
const productImage = new ProductImage(img.name, product.id);
productImage.id = img.id;
productImage.url = `${process.env.APP_API_URL}/files/${img.name}`;
return productImage;
});
return product;
});
return products
}
I need to filter an JS object as below format. I have some array of Object. every object contain title and data. I need to filter the object. title will not repet in object it will make an array of data and store every data in that.
Object
let results = [
{
"title": "exam",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},
{
"title": "prospectus",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},
{
"title": "prospectus",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "23",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},]
Filter object will be like this. title will not be repeated it will make an array.
"results": [
{
"title": "exam",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},
{
"title": "prospectus",
"data": [{
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
},
{
"status": "Active",
"studentId": "44",
"universityId": "23",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}]
I have tried this.
let filterData = [];
mainData.data.results.map((value) => {
if (filterData.length == 0) {
let obj = {
title: "title",
data: [{ ...value.data }],
};
filterData.push(obj);
} else {
let found = false;
}
});
This isn't really a filter operation, more of a reduce job where you want to collect data for the same title.
For that, I'd recommend creating a map of title to data
// this is just your data structure minified
const results = [{"title":"exam","data":{"status":"Active","studentId":"44","universityId":"0","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}},{"title":"prospectus","data":{"status":"Active","studentId":"44","universityId":"0","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}},{"title":"prospectus","data":{"status":"Active","studentId":"44","universityId":"23","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}}];
// Collect data by title
const collect = results.reduce(
(map, { title, data }) => ({
...map,
[title]: [...(map[title] ?? []), data],
}),
{}
);
// Convert the mapped object to an array of objects
// with `title` and `data` properties
const filterData = Object.entries(collect).map(([title, data]) => ({
title,
data,
}));
console.log(filterData);
.as-console-wrapper { max-height: 100% !important; }
This will always put data in an array which keeps your data-structure consistent. If you really want single-element arrays to be destructured, use this instead for the last part
const filterData = Object.entries(collect).map(([title, data]) => ({
title,
data: data.length === 1 ? data[0] : data,
}));
The main problem here is to remember which title already exists and reduce it to just one with the data of all the same titles.
The above solution is good but it has a complexity of O(n^2) because it performs two loops. One to reduce the elements into an array of { title: [datas]} objects and one to transform it into the desired output of the form [{title, datas},...].
Using this solution we can perform the process with a complexity of O(n), using a hash table (directory) structure to remember the titles and reduce only those that are repeated.
let filterData = []
let directory = {}
mainData.data.results.map( (obj) => {
if(directory[obj.title] === undefined) {
directory[obj.title] = filterData.length
filterData.push({title: obj.title, data: [obj.data] })
} else {
filterData[directory[obj.title]].data.push(obj.data)
}
})
var resultObj = {}
results.forEach((item)=>{
if(!resultObj[item.title]){
resultObj[item.title] = {
title:item.title,
data:[]
}
}
resultObj[item.title].data.push(item.data)
})
var finalResultList = Object.values(resultObj)
console.log(finalResultList)
I am reading a simple data set from a data.txt file. I would like to take this data and transform it into a specific object as per my example below. I have managed to get it into a somewhat usable JSON object but this is not ideal. I have included an example of the desired object.
Here is my app.js file:
let output = fs.readFileSync('./data.txt', 'UTF8')
.trim()
.split('\r\n')
.map((line) => line.split(';'))
.reduce((customers, line) => {
customers.push({
name: line[0],
product: [{
item: line[1],
serial: line[2],
year: line[3]
}]
})
return customers
}, [])
console.log(JSON.stringify(output, null, 2))
This currently the above NodeJs code returns the following array object:
[
{
"name": "Nancy",
"product": [
{
"item": "Macbook Pro",
"serial": "A34D05980FCD4303",
"year": "2019"
}
]
},
{
"name": "Nancy",
"product": [
{
"item": "iPad",
"serial": "O0403X3028423C92",
"year": "2015"
}
]
},
{
"name": "Nancy",
"product": [
{
"item": "iPhone",
"serial": "X3830238S3309230",
"year": "2017"
}
]
},
{
"name": "John",
"product": [
{
"item": "Macbook Pro",
"serial": "X2020J393983H380",
"year": "2013"
}
]
},
{
"name": "John",
"product": [
{
"item": "iPhone",
"serial": "X38320093X032309",
"year": "2015"
}
]
},
{
"name": "fluffikins",
"product": [
{
"item": "iMac",
"serial": "F392D392033X3232",
"year": "2013"
}
]
},
{
"name": "fluffikins",
"product": [
{
"item": "iPad",
"serial": "FE322230D3223S21",
"year": "2011"
}
]
}
]
What I am trying to do is get the below object returned - ideally still following the same functional approach:
[
{
"name": "Nancy",
"product": [
{
"item": "Macbook Pro",
"serial": "A34D05980FCD4303",
"year": "2019"
},
{
"item": "iPad",
"serial": "O0403X3028423C92",
"year": "2015"
},
{
"item": "iPhone",
"serial": "X3830238S3309230",
"year": "2017"
}
]
},
{
"name": "John",
"product": [
{
"item": "Macbook Pro",
"serial": "X2020J393983H380",
"year": "2013"
},
{
"item": "iPhone",
"serial": "X38320093X032309",
"year": "2015"
}
]
},
{
"name": "fluffikins",
"product": [
{
"item": "iMac",
"serial": "F392D392033X3232",
"year": "2013"
},
{
"item": "iPad",
"serial": "FE322230D3223S21",
"year": "2011"
}
]
}
]
Here is my mock data set that lives in data.txt
Nancy;Macbook Pro;A34D05980FCD4303;2019
Nancy;iPad;O0403X3028423C92;2015
Nancy;iPhone;X3830238S3309230;2017
John;Macbook Pro;X2020J393983H380;2013
John;iPhone;X38320093X032309;2015
fluffikins;iMac;F392D392033X3232;2013
fluffikins;iPad;FE322230D3223S21;2011
Instead of an array you can use Map in reduce as accumulator, use name as key in Map and club value of all keys, finally just get the values Map to get desired output
const data = `Nancy;Macbook Pro;A34D05980FCD4303;2019
Nancy;iPad;O0403X3028423C92;2015
Nancy;iPhone;X3830238S3309230;2017
John;Macbook Pro;X2020J393983H380;2013
John;iPhone;X38320093X032309;2015
fluffikins;iMac;F392D392033X3232;2013
fluffikins;iPad;FE322230D3223S21;2011`
const final = data.split('\n')
.map(v => v.split(';'))
.reduce((op, [name, item, serial, year]) => {
let obj = { item, serial, year }
if (op.has(name)) {
op.get(name).products.push(obj)
} else{
op.set(name,{name, products:[obj]})
}
return op
}, new Map())
console.log([...final.values()])
Here is a "functional version" that utilizes a Map to find duplicates in O(1):
(map => (
fs.readFileSync('./data.txt', 'UTF8')
.trim()
.split('\r\n')
.map((line) => line.split(';'))
.forEach(([name, item, serial, year]) =>
map.has(name)
? map.get(name).product.push({ item, serial, year })
: map.set(name, { name, product: [{ item, serial, year }] })
),
[...map.values()]
)(new Map)
But seriously, whats so bad about imperative style?:
const customers = new Map;
const entries = fs.readFileSync('./data.txt', 'UTF8')
.trim()
.split('\r\n');
for(const entry of entries) {
const [name, item, serial, year] = entry.split(";");
const product = { item, serial, year };
if(customers.has(name)) {
customers.get(name).product.push(product);
} else customers.set(name, { name, product: [product] });
}
const result = [...customers.values()];
You can modify the .reduce function to only add a new item to the array if there isn't one with that name. If there is, just add the product to that item's product array.
const data = `Nancy;Macbook Pro;A34D05980FCD4303;2019
Nancy;iPad;O0403X3028423C92;2015
Nancy;iPhone;X3830238S3309230;2017
John;Macbook Pro;X2020J393983H380;2013
John;iPhone;X38320093X032309;2015
fluffikins;iMac;F392D392033X3232;2013
fluffikins;iPad;FE322230D3223S21;2011`;
const result = data.trim()
.split('\n')
.map((line) => line.split(';'))
.reduce((customers, line) => {
const product = {
item: line[1],
serial: line[2],
year: line[3]
};
const customer = customers.find(({
name
}) => name === line[0]);
if (customer) {
customer.product.push(product);
} else {
customers.push({
name: line[0],
product: [product]
});
}
return customers
}, []);
console.log(result);
i wanted to move element in nested array. so, here this my data:
let products = [
{
"product_name": "A",
"_id": "5ace995c14a759325776aab1",
"transactions": [
{
"_id": "5ad3a274ac827c165a510f99",
"qty": 100,
"price": 2000
},
{
"_id": "5ad3a274ac827c165a510f99",
"qty": 80,
"price": 1500
},
]
},
{
"product_name": "B",
"_id": "5ace995914a759325776aab0",
"transactions": [
{
"_id": "5ad3a274ac827c165a510f9b",
"qty": 80,
"price": 1500
}
],
}
]
The output that i expected:
[
{
"_id": "5ad3a274ac827c165a510f99",
"qty": 100,
"price": 2000,
"product_name": "A",
},
{
"_id": "5ad3a274ac827c165a510f99",
"qty": 80,
"price": 1500,
"product_name": "A",
},
{
"_id": "5ad3a274ac827c165a510f9b",
"qty": 80,
"price": 1500,
"product_name": "B",
}
]
then, my solve code:
function move() {
var result = []
for (product of products) {
for (transaction of product.transactions) {
transaction.product_name = product.product_name
result.push(transaction)
}
}
return result
}
product = move()
Is there any effective way to create the output, maybe with array map or anything else? Thank you.
You could flat the transactions with Array#reduce and using Object.assign for adding product_name.
Also used:
destructuring assignment for the properties and
short hand properties for taking a variable as property with the name as key.
var products = [{ product_name: "A", _id: "5ace995c14a759325776aab1", transactions: [{ _id: "5ad3a274ac827c165a510f99", qty: 100, price: 2000 }, { _id: "5ad3a274ac827c165a510f99", qty: 80, price: 1500 }] }, { product_name: "B", _id: "5ace995914a759325776aab0", transactions: [{ _id: "5ad3a274ac827c165a510f9b", qty: 80, price: 1500 }] }],
result = products.reduce((r, { transactions, product_name }) =>
r.concat(transactions.map(t => Object.assign({}, t, { product_name }))),
[]
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can reduce and map the transactions to add the product name
let result = products.reduce((c,v)=>{ //Loop the array using reduce
let transactions = v.transactions.map(o=>{ //Loop thru each transactions using map
return Object.assign(o,{"product_name":v.product_name}); //Clone the transaction and add the property product_name
});
return c.concat(transactions); //Merge the current array and the transactions
},[]);
Here is a snippet:
//Your array
let products=[{"product_name":"A","_id":"5ace995c14a759325776aab1","transactions":[{"_id":"5ad3a274ac827c165a510f99","qty":100,"price":2000},{"_id":"5ad3a274ac827c165a510f99","qty":80,"price":1500},]},{"product_name":"B","_id":"5ace995914a759325776aab0","transactions":[{"_id":"5ad3a274ac827c165a510f9b","qty":80,"price":1500}],}]
//The short version
let result = products.reduce((c, v) => c.concat(v.transactions.map(o =>Object.assign(o, {"product_name": v.product_name}))), []);
console.log(result);
Just using js methods you can have your desired output
const products = [
{
"product_name": "A",
"_id": "5ace995c14a759325776aab1",
"transactions": [
{
"_id": "5ad3a274ac827c165a510f99",
"qty": 100,
"price": 2000
},
{
"_id": "5ad3a274ac827c165a510f99",
"qty": 80,
"price": 1500
},
]
},
{
"product_name": "B",
"_id": "5ace995914a759325776aab0",
"transactions": [
{
"_id": "5ad3a274ac827c165a510f9b",
"qty": 80,
"price": 1500
}
],
}
]
let output =[];
products.forEach(elm => elm.transactions.forEach(transaction => {
transaction.product_name = elm.product_name;
output.push(transaction)}));
console.log(output);