order history
I would like to get the total amounts per order, however, I cannot get the value of the quantity in an array
Quantity in an array
I would like to know how to get the value of the quantity in the array so that I can multiply it by to order amount? Or is there another way to get the total amount of the orders?
It's not very clear what you want to do with the quantity, nor how you will get the price of the product, but I try to give some help anyway.
Let's say you have an orders array, if you just need to extract all the quantities you can just do like this:
orders.forEach(order => {
const products = order.products;
products.forEach(product => {
const quantity = product.quantity;
console.log(quantity);
});
});
If you had a function that can give you the price of the single item, for example something like getProductValue() you can compute the total like this:
orders.forEach(order => {
const products = order.products;
products.forEach(product => {
const quantity = product.quantity;
const value = getProductValue(product.id);
const total = quantity * value;
console.log(total);
});
});
You can also create an array with all the amounts like this:
const allAmounts = orders.reduce((valuesList, order) => {
const products = order.products;
const values = products.map(product => {
const quantity = product.quantity;
const value = getProductValue(product.id);
const total = quantity * value;
return total;
});
valuesList = valuesList.concat(values);
return valuesList;
}, []);
Or you can even sum all the values like this:
const totalSum = orders.reduce((totalOrderValue, order) => {
const products = order.products;
const productSum = products.reduce((totalProductValue, product) => {
const quantity = product.quantity;
const value = getProductValue(product.id);
const total = quantity * value;
return totalProductValue += total;
}, 0);
totalOrderValue = totalOrderValue + productSum;
return totalOrderValue;
}, 0);
Here is a complete snippet with a fake orders array and a fake getProductValue function and the totalSum computation:
const orders = [
{
_id: 'xxx',
products: [
{
title: 'ptitle',
id: 'dfsdsge',
quantity: 4,
},
{
title: 'ptitle',
id: 'sdfrer',
quantity: 2,
}
]
},
{
_id: 'dddd',
products: [
{
title: 'ptitle',
id: 'dfsdsge',
quantity: 2,
},
{
title: 'ptitle',
id: 'sdfrer',
quantity: 23,
}
]
},
{
_id: 'eee',
products: [
{
title: 'ptitle',
id: 'dfsdsge',
quantity: 7,
},
{
title: 'ptitle',
id: 'sdfrer',
quantity: 2,
}
]
},
{
_id: 'zzzz',
products: [
{
title: 'ptitle',
id: 'dfsdsge',
quantity: 2,
},
{
title: 'ptitle',
id: 'sdfrer',
quantity: 1,
}
]
},
{
_id: 'hhh',
products: [
{
title: 'ptitle',
id: 'dfsdsge',
quantity: 1,
},
{
title: 'ptitle',
id: 'sdfrer',
quantity: 1,
}
]
},
{
_id: 'wedsd',
products: [
{
title: 'ptitle',
id: 'dfsdsge',
quantity: 78,
},
{
title: 'ptitle',
id: 'sdfrer',
quantity: 8,
}
]
},
{
_id: 'wedsd',
products: [
{
title: 'ptitle',
id: 'dfsdsge',
quantity: 6,
},
{
title: 'ptitle',
id: 'sdfrer',
quantity: 1,
}
]
}
];
const getProductValue = id => {
return 5;
}
const totalSum = orders.reduce((totalOrderValue, order) => {
const products = order.products;
const productSum = products.reduce((totalProductValue, product) => {
const quantity = product.quantity;
const value = getProductValue(product.id);
const total = quantity * value;
return totalProductValue += total;
}, 0);
totalOrderValue = totalOrderValue + productSum;
return totalOrderValue;
}, 0);
console.log(totalSum);
Something along the lines:
let sumOfQuantity = 0;
ORDERS[3].products.forEach(x => {
sumOfQuantity += x.quantity;
})
console.log("Total: " + (ORDERS[3].amount * sumOfQuantity))
If you need to do this for every order just do ORDERS.forEach in the same mannor
Related
I have 2 arrays, one that contains a list of products, and the other is an orders arrays that contains the orderinfo of multiple purchases.
For example, the products array would look like this:
const products = [
{price: 10, id: 123, ...}
,
...
]
and the orders array would look like:
const orders = [
{
shippinginfo: {...},
orderinfo: {
note: 'a message for the seller',
paymentType: 'visa',
products: [
{
id: 123,
qty: 5
}
]
}
}
]
So my question is, how exactly can i go about summing the price of all the orders in this orders array?
Looping through works ! To create it more usable added some random products ... It will give you sum of the all products in array of orders
const orders = [{
orderinfo: {
note: 'a message for the seller',
paymentType: 'visa',
products: [{
id: 123,
qty: 5
},
{
id: 13,
qty: 2
}]
}
}]
const products = [{
price: 10,
id: 123
},
{
price: 100,
id: 13
},
]
let sum = 0;
orders.forEach(order => {
order.orderinfo.products.forEach(item => {
products.forEach(product => {
if (item.id === product.id) {
sum += product.price * item.qty
}
})
})
});
console.log(sum)
We can do something like this:
const products = [{
price: 10,
id: 123
}]
const orders = [{
shippinginfo: "",
orderinfo: {
note: 'a message for the seller',
paymentType: 'visa',
products: [{
id: 123,
qty: 5
}]
}
}];
let obj = {};
products.forEach((product) => {
obj[product.id] = product;
});
orders.forEach((order) => {
order.orderinfo.products.forEach((product) => {
product.price = obj[product.id].price * product.qty;
});
});
console.log(orders);
You can Do it Like This:
const products = [
{price: 10, id: 123}
]
const orders = [
{
shippinginfo: "",
orderinfo: {
note: 'a message for the seller',
paymentType: 'visa',
products: [
{
id: 123,
qty: 5
}
]
}
}
]
var sum = 0
for (let i = 0;i<orders.length;i++){
var order = orders[i]
var orderinfo = order["orderinfo"]
var products1 = orderinfo["products"]
for (let j = 0;j<products1.length;j++){
var product1 = products1[j]
for (let k = 0;k<products.length;k++){
if (products[k]["id"] == product1["id"]){
sum += products[k]["price"]*product1["qty"]
}
}
}
}
console.log(sum); // 50
const orders = [{
orderinfo: {
note: 'a message for the seller',
paymentType: 'visa',
products: [{
id: 123,
qty: 5
},
{
id: 13,
qty: 2
}]
}
}]
const products = [{
price: 10,
id: 123
},
{
price: 100,
id: 13
},
]
// finds price of order's product and multiply by qty
let sumOfOrders = orders.orderinfo.products.reduce((acc, cur) => acc + (products.find(f => f.id === cur.id)).price * cur.qty)
Assign at least one unique item to each users at random. e.g if 5 items & 5 users, each users get 1 items. if 4 items & 5 users, only 4 users get 1 items each. if 7 items & 4 users, then 3 users get 2 items each & 1 user get 1 item and so on. The script below was meant to achieved this but got a wrong result.
assignItemsToUsers() {
let items = [
{
id: 1,
name: "item1",
tag: 1900
},
{
id: 2,
name: "item2",
tag: 1876
},
{
id: 3,
name: "item3",
tag: 1575
},
{
id: 4,
name: "item4",
tag: 4783
},
{
id: 5,
name: "item5",
tag: 67894
},
{
id: 6,
name: "item6",
tag: 66789
},
{
id: 7,
name: "item7",
tag: 67890
},
{
id: 8,
name: "item8",
tag: 87654
},
{
id: 9,
name: "item9",
tag: 94948
}
];
let users = [
{
id: 1,
name: "user1",
userID: 38494
},
{
id: 2,
name: "user2",
userID: 84844
},
{
id: 3,
name: "user3",
userID: 47483
},
{
id: 4,
name: "user4",
userID: 83735
}
];
let results = [];
let tempResults = [];
for (let i = 0; i < items.length; i++) {
const item = items[i];
const randomUser = users[Math.floor(Math.random() * users.length)];//pick user at random
randomUser.tempitem = item;//asign item to this user
tempResults.push(randomUser);//push to tempResults
}
//Group assigned items to their respective user
for (let i = 0; i < users.length; i++) {
const user = users[i];
let myluckyitems = [];
for (let index = 0; index < tempResults.length; index++) {
//check where tempResults[index].id == user.id
const assigneduser = tempResults[index];
if (user.id == assigneduser.id) {
//True: this was the assigned user.
myluckyitems.push(assigneduser.tempitem);
}
}
//all items assigned, then append to user object & push to results
if (myluckyitems.length > 0) {
user.items = myluckyitems;
results.push(user);
}
}
console.log(results);
}
Actual Result
results = [
{
id: 1,
name: user1,
userID: 38494,
items: [
{
id: 1,
name: item1,
tag: 1900
},
{
id: 1,
name: item1,
tag: 1900
}
],
tempitem: {
id: 1,
name: item1,
tag: 1900
},
},
{
id: 2,
name: user2,
userID: 84844,
items: [
{
id: 2,
name: item2,
tag: 1876
},
{
id: 2,
name: item2,
tag: 1876
},
{
id: 2,
name: item2,
tag: 1876
},
],
tempitem: {
id: 2,
name: item2,
tag: 1876
},
},
{
id: 3,
name: user3,
userID: 47483,
items: [
{
id: 3,
name: item3,
tag: 1575
},
{
id: 3,
name: item3,
tag: 1575
}
],
tempitem: {
id: 3,
name: item3,
tag: 1575
},
},
{
id: 4,
name: user4,
userID: 83735,
items: [
{
id: 4,
name: item4,
tag: 4783
},
{
id: 4,
name: item4,
tag: 4783
}
],
tempitem: {
id: 4,
name: item4,
tag: 4783
},
}
];
Expected Results
results = [
{
id: 1,
name: user1,
userID: 38494,
items: [
{
id: 1,
name: item1,
tag: 1900
},
{
id: 5,
name: item5,
tag: 67894
},
{
id: 9,
name: item9,
tag: 94948
}
],
},
{
id: 2,
name: user2,
userID: 84844,
items: [
{
id: 2,
name: item2,
tag: 1876
},
{
id: 6,
name: item6,
tag: 66789
},
],
},
{
id: 3,
name: user3,
userID: 47483,
items: [
{
id: 3,
name: item3,
tag: 1575
},
{
id: 7,
name: item7,
tag: 67890
},
],
},
{
id: 4,
name: user4,
userID: 83735,
items: [
{
id: 4,
name: item4,
tag: 4783
},
{
id: 8,
name: item8,
tag: 87654
},
],
}
];
The difference is that, the actual results returns repeated items for each users and not all items were assigned to users, it also appends the tempitem property to each user which is not needed.
The expected results, assigns unique items to each users without repetition and also ensure that an item must be assigned to a user.
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
function assign() {
const itemsLength = items.length;
for (var i=itemsLength+1, shuffledArray=[]; i--;) shuffledArray.push(i);
shuffledArray = shuffleArray(shuffledArray);
const eachUserItems = itemsLength/users.length;
Object.entries(users).map(([key, value]) => {
for(i = 0; i < Math.round(eachUserItems); i++) {
users[key]['items'] = users[key]['items'] || [];
var popNewIndex = shuffledArray.pop();
var objectToInsert = items.find((i) => i.id == popNewIndex + 1);
users[key]['items'].push(objectToInsert);
}
});
return users;
}
This would give you expected items always assigned randomly to users
ps.
Also simple idea here is that rather than randomising on every loop we would make a random list of values that we would pop one by one. We can use randomise value to fetch value out of list by id and assign it. As list is supposed to have unique values which are randomised it would make sure no value is assigned again to any other user.
You can do something like that (excuse me for possible mistakes, I didnt test it)
const users = [...]
const items = [...]
const results = []
const random_func = () => {
let available_users = [...users]
items.forEach(item => {
// if available users are zero, re-populate the array (it means that everyone has a item
if(available_users.length === 0) available_users = [...users]
//get a random user from available users array
const random_user_index = Math.floor(Math.random() * available_users.length)
const temp_user = available_users(random_user_index)
//remove user from available users
available_users.splice(i, 1);
//check if user already exists into results array
if(results.length > 0) {
objIndex = results.findIndex((obj => obj.id == temp_user.id));
if(objIndex === -1) results.push({...temp_user, items: [{...item}]}
else results[index].items.push(item)
}else {
results.push({...temp_user, items: [{...item}]}
}
})
}
Check the following code. It's tested and produces the expected result.
const minItems = Math.round(items.length / users.length);
const assignedItems = [];
const usersWithItems = users.map((user) => {
user.items = new Array(minItems).fill(0).map(() => {
let isNew = false;
let item;
do {
item = items[Math.floor(Math.random() * items.length)];
if(!assignedItems.includes(item.id))
isNew = true;
} while(isNew == false);
if(item){
assignedItems.push(item.id);
return item;
}
});
return user;
})
const balanceItems = items.filter(item => !assignedItems.includes(item.id));
balanceItems.forEach((item) => {
const randomUserNo = Math.floor(Math.random() * users.length);
usersWithItems[randomUserNo].items.push(item);
})
console.log(usersWithItems);
Lets's try to simplify your task, lets imagine you have unknown number of elements
const items = [1, 5, 6, 7, 3, 4, 2, 3, 2];
and unknown number of users
const users = [{ name: "Tom", items: []}, { name: "John", items: [] }, name: "Steve", items: [] }];
and you have to assign those items to user so your code would be
const items = [1, 5, 6, 7, 3, 4, 2, 3, 2];
const users = [{ name: "Tom", items: []}, { name: "John", items: [] }, { name: "Steve", items: [] }];
let currentUserIndex = 0;
while (items.length) {
const randomIndex = Math.floor(Math.random() * items.length);
users[currentUserIndex].items.push(items[randomIndex]);
items.splice(randomIndex, 1);
if (currentUserIndex === users.length - 1) {
currentUserIndex = 0;
} else {
currentUserIndex++;
}
}
const products = [
{
id: 5,
productName: "Logitech Mouse",
unitprice: 35
},
{
id: 6,
productName: "Logitech Keyboard",
unitprice: 40
}
];
const carts = [
{
id: 101,
userId: 3,
productId: 5,
quantity: 2,
total: function () {
return this.unitprice * this.quantity
}
}
];
let joined = carts.map(item => {
console.log(item.total);
let { id, ...rest } = products.find(p => p.id === item.productId);
debugger
return {
...rest, 'quantity': item.quantity,
'total': item.total
};
});
console.log(joined);
How do I get the total property for the new object at the end? I tried with the above but the total value 10 is not there. I tried another version at below but still no success.
get total() {
return this.unitprice * this.quantity
}
A getter would work, the only issue is, it won't have access to the unit price. You will have to pass through the unit price.
const products = [{
id: 5,
productName: "Logitech Mouse",
unitprice: 35
},
{
id: 6,
productName: "Logitech Keyboard",
unitprice: 40
}
];
const carts = [{
id: 101,
userId: 3,
productId: 5,
quantity: 2,
total: function(unitprice) {
return unitprice * this.quantity
}
}];
let joined = carts.map(item => {
let {
id,
unitprice,
...rest
} = products.find(p => p.id === item.productId);
debugger
return {
...rest,
'quantity': item.quantity,
'total': item.total(unitprice)
};
});
console.log(joined);
u can try:
const products = [
{
id: 5,
productName: "Logitech Mouse",
unitprice: 35
},
{
id: 6,
productName: "Logitech Keyboard",
unitprice: 40
}
];
const carts = [
{
id: 101,
userId: 3,
productId: 5,
quantity: 2,
total: function () {
return products.find(product => product.id === this.productId).unitprice * this.quantity;
}
}
];
let joined = carts.map(item => {
console.log(item.total());
let { id, ...rest } = products.find(p => p.id === item.productId);
return {
...rest, "quantity": item.quantity,
"total": item.total
};
});
console.log(joined);
let joined = carts.filter((ca)=>{
return products.some((c)=>{
//place your exact calculations here(c.id === ca.productId)
// ca.total = -- your result
return c;
})
});
Try this way.
var ingredients = [
{ name: 'potatoes', quantity: 4 },
{ name: 'butter', quantity: 1 },
{ name: 'milk', quantity: 1, description: '1 cup' },
{ name: 'potatoes', quantity: 3 },
{ name: 'oil', quantity: 1, description: '3 cups' } ];
const shoppingList = [];
for (let i = 0; i < ingredients.length; i ++) {
for (let j = 0; j < shoppingList.length; j ++){
let ingredient = ingredients[i];
let shoppingListItem = shoppingList[j];
if(ingredient === shoppingListItem){
break;
}else if (roughDraftItem.name === shoppingListItem.name){
shoppingListItem.quantity += roughDraftItem.quantity;
} else {shoppingList.push(roughDraftItem);
}
}
}
When I run this code the shoppingList array comes back empty. When I take out the second loop the code doesn't have a problem and I get what I need
shoppingListItem = { name: 'potatoes', quantity: 1}
It seems to be a problem of trying to compare the Ingredients array to the shoppingList array (after an object has been added).
Your shoppingList is empty so its length = 0. The second loop of the array doesn't run, since it's told to run 0 times.
You don't need the second loop to add an object to the shoppingList, so I would remove it.
As others have said, shoppingList starts with a length of 0, so the 2nd loop will never run. Also, if you're trying to sum the quantity of items with the same name, you could use reduce to simplify things:
const ingredients = [
{ name: 'potatoes', quantity: 4 },
{ name: 'butter', quantity: 1 },
{ name: 'milk', quantity: 1, description: '1 cup' },
{ name: 'potatoes', quantity: 3 },
{ name: 'oil', quantity: 1, description: '3 cups' } ];
const result = ingredients.reduce((acc, curr) => {
const exists = acc.find(item => item.name === curr.name);
if (exists) {
exists.quantity += curr.quantity;
return acc;
}
return [...acc, curr]
}, []);
console.log(result);
You can use Array.prototype.reduce and ES6 object destructuring assignment to make an aggregation of ingredients by their name, and Array.prototype.map to generate the desired output:
This solution is more declarative than nested for loops and can work with any amount of repetitive items:
var ingredients = [
{ name: 'potatoes', quantity: 4 },
{ name: 'butter', quantity: 1 },
{ name: 'milk', quantity: 1, description: '1 cup' },
{ name: 'potatoes', quantity: 3 },
{ name: 'oil', quantity: 1, description: '3 cups' }
];
// Aggregate `quantity` by `name`
var dataObj = ingredients.reduce((all, {name, quantity}) => {
all[name] = (all[name] || 0) + quantity;
return all;
}, {});
// Generate the result
var shoppingList = Object.keys(dataObj).map(ing => ({name: ing, quantity: dataObj[ing]}));
console.log(shoppingList);
Input:
const data = [
{
id: 'RS11',
name: 'Road 1',
quantity: {
lengthVal: 50
}
},
{
id: 'RS11',
name: 'Road 1',
quantity: {
lengthVal: 100
}
},
{
id: 'RS11',
name: 'Road 2',
quantity: {
lengthVal: 20
}
}
]
Each property except quantity should be grouped. quantity.lengthVal should be summarized. A count property should also be added.
Expected output:
const expected = [
{
id: 'RS11',
name: 'Road 1',
count: 2,
summarizedLength: 150
},
{
id: 'RS11',
name: 'Road 2',
count: 1,
summarizedLength: 20
}
]
This is what i tried:
const groupAndSum = (arr) => {
return _.chain(arr)
.groupBy((obj) => {
// Some reduce here?
return _.values(_.without(obj), 'quantity').join('|')
})
.map((val) => {
val[0].count = val.length;
delete val[0].quantity;
return val[0];
})
.value();
}
Jsbin: https://jsbin.com/totujopume/edit?html,js,console
Dataset is quite big so performance is important.
Can do this with a fairly simple native reduce() that only makes one iteration through the array for whole procedure
const res = Object.values(
data.reduce((a, c) => {
const key = c.id + '|' + c.name;
const o = a[key] = a[key] || c;
o.count = (o.count || 0) +1;
o.summarizedLength = (o.summarizedLength || 0) + c.quantity.lengthVal;
delete c.quantity;
return a;
},{})
);
console.log(res)
.as-console-wrapper { max-height: 100%!important;}
<script>
const data = [{
id: 'RS11',
name: 'Road 1',
quantity: {
lengthVal: 50
}
},
{
id: 'RS11',
name: 'Road 1',
quantity: {
lengthVal: 100
}
},
{
id: 'RS11',
name: 'Road 2',
quantity: {
lengthVal: 20
}
}
]
</script>