I'm playing around with E-commerce application. I have API call, api call returns Data like below, I want to paint all images inside products to HTML using map function, now it's returns single generated element, what I am doing wrong? thanks in advance
var Result = {
purchases: [{
products: [{
product_id: 264772179145,
name: "Acer Chromebook 315 15.6",
image_url: "https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"
},
{
product_id: 264772179145,
name: "Acer Chromebook 315 15.6",
image_url: "https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"
},
],
timestamp: 1618215999,
amount: 73457
},
{
products: [{
product_id: 264772179145,
name: "Acer Chromebook 315 15.6",
image_url: "https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"
}],
timestamp: 1618216092,
amount: 73457
},
{
products: [{
product_id: 154061997658,
name: "adidas Wheeled Team Bag Men`s",
image_url: "https://i.ebayimg.com/00/s/MTYwMFgxNjAw/z/JYAAAOSwwRZf9n2L/$_1.JPG?set_id=880000500F"
}],
timestamp: 1618217956,
amount: 34566
}
],
};
function getProducts() {
var res;
var purchases = Result.purchases.map(purchases => {
var x = purchases.amount;
res = purchases.products.map(el => {
return `<div class="all-img"><img style="height:50px"; width:50px; src="${el.image_url}">
<div class="amount">${x}</div>
</div>`
})
})
document.getElementById("transactionBoxes").innerHTML = res.join('')
}
<div id="transactionBoxes">
</div>
<button onclick="getProducts()">append</button>
I shortened the function so you won't have to use the return keyword and the extra variables
var Result = {"purchases":[{"products":[{"product_id":264772179145,"name":"Acer Chromebook 315 15.6","image_url":"https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"},{"product_id":264772179145,"name":"Acer Chromebook 315 15.6","image_url":"https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"},{"product_id":264772179145,"name":"Acer Chromebook 315 15.6","image_url":"https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"},{"product_id":264772179145,"name":"Acer Chromebook 315 15.6","image_url":"https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"}],"timestamp":1618215999,"amount":73457},{"products":[{"product_id":264772179145,"name":"Acer Chromebook 315 15.6","image_url":"https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F"}],"timestamp":1618216092,"amount":73457},{"products":[{"product_id":154061997658,"name":"adidas Wheeled Team Bag Men`s","image_url":"https://i.ebayimg.com/00/s/MTYwMFgxNjAw/z/JYAAAOSwwRZf9n2L/$_1.JPG?set_id=880000500F"}],"timestamp":1618217956,"amount":34566}]};
function getProducts() {
const purchases = Result.purchases.map(purchase => purchase.products.map(el => `<div class="all-img"><img style="height:50px"; width:50px; src="${el.image_url}"><div class="amount">${purchase.amount}</div></div>`).join(''));
document.getElementById("transactionBoxes").innerHTML = purchases.join('');
}
document.querySelector('button').addEventListener('click', getProducts);
<div id="transactionBoxes"></div>
<button>append</button>
You can improve two things here:
You can nest map functions to be sure to render your whole collection
style="height:50px"; width:50px; => style="height:50px; width:50px;"
var Result = {
purchases: [
{
products: [
{
product_id: 264772179145,
name: 'Acer Chromebook 315 15.6',
image_url: 'https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F',
},
{
product_id: 264772179145,
name: 'Acer Chromebook 315 15.6',
image_url: 'https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F',
},
],
timestamp: 1618215999,
amount: 73457,
},
{
products: [
{
product_id: 264772179145,
name: 'Acer Chromebook 315 15.6',
image_url: 'https://i.ebayimg.com/00/s/MTAwMFgxMDAw/z/EAcAAOSw6pJe8Lwo/$_1.JPG?set_id=880000500F',
}],
timestamp: 1618216092,
amount: 73457,
},
{
products: [
{
product_id: 154061997658,
name: "adidas Wheeled Team Bag Men's",
image_url: 'https://i.ebayimg.com/00/s/MTYwMFgxNjAw/z/JYAAAOSwwRZf9n2L/$_1.JPG?set_id=880000500F',
}],
timestamp: 1618217956,
amount: 34566,
},
],
};
function getProducts() {
var res = Result.purchases
.map((purchases) => {
return purchases.products
.map((product) => {
return (`
<div class="all-img">
<img style="height:50px; width:50px;" src="${product.image_url}" alt="${product.name}" />
<div class="amount">${purchases.amount}</div>
</div>
`)
})
.join('')
})
.join('');
document.getElementById('transactionBoxes').innerHTML = res;
}
<div id="transactionBoxes"></div>
<button onclick="getProducts()">append</button>
You should also read the map documentation, you tried to use it as a for/forEach function.
Try surrounding the return statement with parentheses. I program in React Native and it is required to surround the return with parentheses if it has multiple lines.
res = purchases.products.map(el => {
return (`<div class="all-img"><img style="height:50px"; width:50px; src="${el.image_url}">
<div class="amount">${x}</div>
</div>`)
})
Related
In my Vue app, I have a reduce function that's being called within an html/vue loop and it's taking far too long; around 21 seconds
During that time, nothing renders and the page freezes temporarily
I think part of the issue is that I'm calling the computed property in a loop and it calls the reduce function each time, but I'm still unclear on a way to optimize this to quickly go through the reduce function and allow the loop to only hit the result set as opposed to reducing through each iteration.
My result set is about 12,000 records but I've only included a few in the exact structure.
What can I do here?
<script>
const reduceFunction = (rows) =>
rows .reduce(
(a, row) => {
const employee = a [row .employee] || (a [row .employee] = {dates: {}, total_categories:0, total_items: 0, area: '', group: ''})
const date = employee .dates [row .itemDate] || (employee .dates [row .itemDate] = {categories: 0, qty: 0, total_categories: 0, unavailable: 0, orders: {}})
date.categories += +row.categories_per_item * +row.qty
date.qty += +row.qty
date.total_categories = date.categories
const order = date .orders [row .order_number] || (date .orders [row .order_number] = {itemDate: '', skus: {}})
order.itemDate = row.itemDate;
const sku = order .skus [row .sku] || (order .skus [row .sku] = {categories: '', qty: '', itemDate: '', expected: '', created: '', unavailable: 0, available:0})
sku.categories += row.categories_per_item
sku.qty += row.qty
sku.itemDate = row.itemDate
sku.expected = row.shipDate
sku.created = row.created_date
sku.heir_id = row.heir_identifier
employee.total_categories += (+row.categories_per_item * +row.qty)
employee.total_items += (+row.qty)
employee.area = row.area
employee.group = row.group_name
employee.warehouse = row.warehouse
employee.locale = row.locale
const foundKit = vm.$data.kitsData.find((kit) => kit.heir_identifier === sku.heir_id)
if (foundKit) {
new_avail = 10;
if(sku.qty > new_avail){
status.status = "Not available";
date.unavailable += 1
sku.unavailable += 1
}else{
status.status = "Available"
}
}else{
status.status = "No item found"
}
return a
},
{}
);
var vm =
new Vue({
el: "#app",
data: {
rows: [
{
employee: "Adam",
sku: "A1453",
categories_per_item: "15",
area: "1",
itemDate: "2021-11-02",
qty: 37,
group_name: "managers",
warehouse: "3",
order_number: "1234",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC3"
},
{
employee: "Joan",
sku: "A1453",
categories_per_item: "15",
area: "1a",
itemDate: "2021-11-02",
qty: 17,
group_name: "managers",
warehouse: "3",
order_number: "34578",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC3"
},
{
employee: "Bill",
sku: "A1453",
categories_per_item: "15",
area: "1",
itemDate: "2021-11-03",
qty: 57,
group_name: "managers",
warehouse: "3",
order_number: "2345",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC3"
},
{
employee: "PJ",
sku: "A6512",
categories_per_item: "150",
area: "2",
itemDate: "2021-11-03",
qty: 20,
group_name: "managers",
warehouse: "3",
order_number: "34567",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC1"
}
]
},
methods: {
},
computed: {
employeeData() {
console.log('employee data')
employeeRows = reduceFunction(this.rows)
return employeeRows
console.log(employeeRows)
},
dates() {
return Array.from(Array(11), (_, i) => new Date(Date.now() + i * 86400000).toISOString().slice(0,10))
}
}
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<tr v-for="(value, employee) in employeeData" :key="employee">
<td>#{{employee}}</td>
<td v-for="date in dates" :key="date" >
<div v-for="(dateInfo, dateValue) in value.dates" :key="dateValue" >
<div v-if="dateValue == date ">
#{{ dateInfo.total_categories }}
</div>
</div>
</td>
</tr>
</div>
My approach for this problem would be to invoke reduceFunction on mounted(){}
and create another state for the array, here I called it parsedRows
So basically to avoid unnecessary re rendering.
data: {
rows: []
parsedRows: []
}
methods: {
reduceFunction(data){
//adjust your code to fit method here
}
}
mounted(){
this.parsedRows = this.reduceFunction(this.rows);
}
and then use the parsedRows on the Vue template.
Also to move the reduceFunction to methods
The main improvement I could see would be to eliminate the nested loop here:
const foundKit = vm.$data.kitsData.find((kit) => kit.heir_identifier === sku.heir_id)
Organize the kitsDat by heir_identifier first so you can look up in O(1) instead of .finding (O(n)) each time.
const kitsByHeir = new Map();
for (const kit of vm.$data.kitsData) {
kitsByHeir.set(kit.heir_identifier, kit);
}
Then do kitsByHeir.get(sku.heir_id) inside the loop.
You might also use a for loop instead of reduce (reduce is arguably not appropriate in this situation anyway)
Also, processing 12,000 records on the client-side is pretty odd. Even with the best designed code, that could take an uncomfortable amount of time in certain environments. Consider moving the processing to a server instead.
[Noob to Javascript and React] I am using an API that returns an object with values like this. AAPL, AMZN, FB, GOOGL, can be anything based on the function's string array input.
{
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
How could I consider dynamically mapping a response like this into a state object like this? The id property doesn't exist, it needs to be created.
state = {
stocks: [ { id: 1, name: 'AAPL', price: 329.99 }, { id: 2, name: 'AMZN', price: 2563.05 }, ...]
}
I'm able to successfully print the stock names and their prices separately but I am having trouble figuring out how I could wire them into a state object like what's above.
function getCurrentPriceOfBatchStocks(_stocks) {
iex
.symbols(_stocks)
.price()
.then(res => {
console.log(typeof res);
console.log(res);
console.log(Object.keys(res));
console.log(Object.values(res));
});
}
Not sure where you're getting id from, so I'm using idx as an example.
const stocks = Object.keys(resp).map((key, idx) => ({ id: idx + 1, name: key, price: resp[key] }))
Here is an implementation. With Object.entries, you get an array with an array of [key, value] of your original object. And you can map this array to a different format.
You can check the result with the Run code snippet button.
let st = {
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
let stocks = Object.entries(st).map(([key, value], index) => ({id: index + 1, name: key, price: value.price}))
console.log(stocks)
const res={
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
console.log(Object.entries(res).map((entry,index)=>{
return {
id:index+1,
name:entry[0],
...entry[1]
}
}));
I have an n levels deep nested array of tag objects with title and ID. What I'm trying to create is a an object with IDs as keys and values being an array describing the title-path to that ID.
I'm no master at recursion so my attempt below doesn't exactly provide the result I need.
Here's the original nested tag array:
const tags = [
{
title: 'Wood',
id: 'dkgkeixn',
tags: [
{
title: 'Material',
id: 'ewyherer'
},
{
title: 'Construction',
id: 'cchtfyjf'
}
]
},
{
title: 'Steel',
id: 'drftgycs',
tags: [
{
title: 'Surface',
id: 'sfkstewc',
tags: [
{
title: 'Polished',
id: 'vbraurff'
},
{
title: 'Coated',
id: 'sdusfgsf'
}
]
},
{
title: 'Quality',
id: 'zsasyewe'
}
]
}
]
The output I'm trying to get is this:
{
'dkgkeixn': ['Wood'],
'ewyherer': ['Wood', 'Material'],
'cchtfyjf': ['Wood', 'Construction'],
'drftgycs': ['Steel'],
'sfkstewc': ['Steel', 'Surface'],
'vbraurff': ['Steel', 'Surface', 'Polished'],
'sdusfgsf': ['Steel', 'Surface', 'Coated'],
'zsasyewe': ['Steel', 'Quality']
}
So I'm building this recursive function which is almost doing it's job, but I keep getting the wrong paths in my flat/key map:
function flatMap(tag, acc, pathBefore) {
if (!acc[tag.id]) acc[tag.id] = [...pathBefore];
acc[tag.id].push(tag.title);
if (tag.tags) {
pathBefore.push(tag.title)
tag.tags.forEach(el => flatMap(el, acc, pathBefore))
}
return acc
}
const keyMap = flatMap({ title: 'Root', id: 'root', tags}, {}, []);
console.log("keyMap", keyMap)
I'm trying to get the path until a tag with no tags and then set that path as value for the ID and then push the items 'own' title. But somehow the paths get messed up.
Check this, makePaths arguments are tags, result object and prefixed titles.
const makePaths = (tags, res = {}, prefix = []) => {
tags.forEach(tag => {
const values = [...prefix, tag.title];
Object.assign(res, { [tag.id]: values });
if (tag.tags) {
makePaths(tag.tags, res, values);
}
});
return res;
};
const tags = [
{
title: "Wood",
id: "dkgkeixn",
tags: [
{
title: "Material",
id: "ewyherer"
},
{
title: "Construction",
id: "cchtfyjf"
}
]
},
{
title: "Steel",
id: "drftgycs",
tags: [
{
title: "Surface",
id: "sfkstewc",
tags: [
{
title: "Polished",
id: "vbraurff"
},
{
title: "Coated",
id: "sdusfgsf"
}
]
},
{
title: "Quality",
id: "zsasyewe"
}
]
}
];
console.log(makePaths(tags));
Task
There is an array of objects of the form:
{
title: 'Macbook Air',
offers: [
{
seller: 'Avic',
price: 1200
},
{
seller: 'Citrus',
price: 1600
}
]
}
It is necessary to Convert to an array of objects of the form:
{
title: 'Macbook Air',
bestOffer: {
name: 'Avic',
price: 1200
}
}
Where bestOffer is an offer with a minimum price value.
Write in one line using map() and find().
Code
"use_strict";
var productList = [
{
title: "Product X1",
offers: [
{
seller: "Company X1",
price: 400
},
{
seller: "Company X2",
price: 200
},
{
seller: "Company X3",
price: 300
}
]
},
{
title: "Product Y1",
offers: [
{
seller: "Company Y1",
price: 1700
},
{
seller: "Company Y2",
price: 1600
},
{
seller: "Company Y3",
price: 1500
},
{
seller: "Company Y4",
price: 1400
}
]
},
{
title: "Product Z1",
offers: [
{
seller: "Company Z1",
price: 50
},
{
seller: "Company Z2",
price: 60
},
{
seller: "Company Z3",
price: 10
},
{
seller: "Company Z4",
price: 90
},
{
seller: "Company Z5",
price: 70
}
]
}
];
const destinations = productList.map(item =>
({
title: item.title,
bestOffer: ({
name: item.offers[0].seller, // TODO: How to implement find() method????
price: item.offers[0].price
})
})
)
console.log(destinations)
My code work for restructuring objects for new array, BUT i dont know how to implement find() method for searching minimal value. Is it possible using find() method in this case??
You can use Array.reduce() to find the best offer by price. On each iteration check if the current item's (o) price is less than the accumulator's (r) price, and take the one with the lowest.
const productList = [{"title":"Product X1","offers":[{"seller":"Company X1","price":400},{"seller":"Company X2","price":200},{"seller":"Company X3","price":300}]},{"title":"Product Y1","offers":[{"seller":"Company Y1","price":1700},{"seller":"Company Y2","price":1600},{"seller":"Company Y3","price":1500},{"seller":"Company Y4","price":1400}]},{"title":"Product Z1","offers":[{"seller":"Company Z1","price":50},{"seller":"Company Z2","price":60},{"seller":"Company Z3","price":10},{"seller":"Company Z4","price":90},{"seller":"Company Z5","price":70}]}]
const findBestOffer = ({ offers = [] }) => offers
.reduce((r, o) => o.price < r.price ? o : r)
const formatOffer = item => item ? ({
name: item.seller,
price: item.price
}) : 'none'
const destinations = productList.map(item => ({
title: item.title,
bestOffer: formatOffer(findBestOffer(item))
}))
console.log(destinations)
If you need to use Array.map() and Array.find() - map the array to the price numbers, and get the lowest one using Math.min(), and then find the item with that price:
const productList = [{"title":"Product X1","offers":[{"seller":"Company X1","price":400},{"seller":"Company X2","price":200},{"seller":"Company X3","price":300}]},{"title":"Product Y1","offers":[{"seller":"Company Y1","price":1700},{"seller":"Company Y2","price":1600},{"seller":"Company Y3","price":1500},{"seller":"Company Y4","price":1400}]},{"title":"Product Z1","offers":[{"seller":"Company Z1","price":50},{"seller":"Company Z2","price":60},{"seller":"Company Z3","price":10},{"seller":"Company Z4","price":90},{"seller":"Company Z5","price":70}]}]
const findBestOffer = ({ offers = [] }) => {
const min = Math.min(...offers.map(o => o.price))
return offers.find(o => o.price === min)
}
const formatOffer = item => item ? ({
name: item.seller,
price: item.price
}) : 'none'
const destinations = productList.map(item => ({
title: item.title,
bestOffer: formatOffer(findBestOffer(item))
}))
console.log(destinations)
Since you prefer to use FIND and MAP, I have a clearer solution for you then.
// product list
const productList = [{"title":"Product X1","offers":[{"seller":"Company X1","price":400},{"seller":"Company X2","price":200},{"seller":"Company X3","price":300}]},{"title":"Product Y1","offers":[{"seller":"Company Y1","price":1700},{"seller":"Company Y2","price":1600},{"seller":"Company Y3","price":1500},{"seller":"Company Y4","price":1400}]},{"title":"Product Z1","offers":[{"seller":"Company Z1","price":50},{"seller":"Company Z2","price":60},{"seller":"Company Z3","price":10},{"seller":"Company Z4","price":90},{"seller":"Company Z5","price":70}]}]
// Search text from Collection
function searchProduct(niddle, haystack){
const searchResult = haystack.find(item=> item['title'] === niddle);
let bestOffer;
if(searchResult){
bestOffer = getBestOffer(searchResult);
}
return bestOffer;
}
// Search for best Offer
function getBestOffer(dataInfo){
let bestOffer = {seller: null,price: null};
dataInfo['offers'].map((item, index)=>{
if(bestOffer.price === null || bestOffer.price > item.price){
bestOffer = item;
}
})
return bestOffer;
}
//run
console.log( searchProduct("Product Z1", productList) );
//output is
// Object {seller: "Company Z3", price: 10}
I hope you like it.
In my React app, I'm looking for a clean way to loop through the following dynamic data structure and display the object properties and values.
Sample data:
data: {
company: [
{
company_name: "XYZ Firm",
company_email: "hello#xyz.com",
company_phone: 91982712,
}
],
shareholders: [
{
shareholder_name: "Lin",
percentage: 45
},
{
shareholder_name: "Alex",
percentage: 10
},
],
employees: [
{
employee_name: "May",
employee_email: "may#xyz.com"
},
]
}
The output I want is:
company_name: XYZ Firm
company_email: hello#xyz.com
company_phone: 91982712
shareholder_name: Lin
shareholder_percentage: 45
shareholder_name: Alex
shareholder_percentage: 10
employee_name: May
employee_email: may#xyz.com
This is what I've tried so far:
//data contains the entire object
const profileInfo = Object.keys(data).map(key => {
let profileSection = [];
for (let values of data[key]) { //retrieve the objects of each "section" e.g., company, shareholders
Object.keys(values).map(key => {
profileSection.push(<p>{key}: {values[key]}</p>);
})
}
return profileSection;
})
I'm able to achieve the intended results but I'm not sure if it's the best solution in terms of performance. Having nested Object.keys().mapseems a bit off to me.
Note: User will be able to add more shareholders/employees.
Here is a somewhat shorter version using Object.values() and Object.entries().
var data = { company: [ { company_name: "XYZ Firm", company_email: "hello#xyz.com", company_phone: 91982712, } ], shareholders: [ { shareholder_name: "Lin", percentage: 45 }, { shareholder_name: "Alex", percentage: 10 }, ], employees: [ { employee_name: "May", employee_email: "may#xyz.com" }, ] };
let profileInfo = [];
Object.values(data).flat().forEach((item) => {
Object.entries(item).forEach(([key, value]) => {
profileInfo.push(key + ": " + value);
});
});
console.log(profileInfo);