I have two arrays:
let array1 = [
{
_id: '5eaf8eeac436dbc9b7d75f35',
name: 'Strawberry',
category: 'organic',
image: '/productImages/australian.jpg',
price: '9.65',
quantity: 1
},
{
_id: '5eaf8f61c436dbc9b7d75f36',
name: 'Organic Wild Blue Berry',
category: 'organic',
image: '/productImages/owbb.jpg',
price: '12.50',
quantity: 1
},
{
_id: '5eb0ac47d98c817d9a82df82',
name: 'Mango',
category: 'australian',
image: '/productImages/australian.jpg',
price: '12.25',
quantity: 1
},
{
_id: '5eb0ac71d98c817d9a82df83',
name: 'Peas',
category: 'conventional',
image: '/productImages/owbb.jpg',
price: '25.12',
quantity: 1
}
]
let array2 = [
{
_id: '5ec00539f7ff70566fd8a557',
productid: {
_id: '5eaf8eeac436dbc9b7d75f35',
name: 'Strawberry',
category: 'organic',
image: '/productImages/australian.jpg',
price: '9.65'
},
quantity: 3
},
{
_id: '5ec00539f7ff70566fd8a558',
productid: {
_id: '5eaf8f61c436dbc9b7d75f36',
name: 'Organic Wild Blue Berry',
category: 'organic',
image: '/productImages/owbb.jpg',
price: '12.50'
},
quantity: 3
}
]
I need to check if productId of array2 matches any object _id of array1. If so, I need to add each object's quantities to one another. Otherwise, I need to push one to another.
For example, if "_id": "5eb0ac71d98c817d9a82df83" doesn't exist in any object of array2's productId, push it into array2. And if any element of array2 doesn't exist in array1, push it into array1.
I managed to update the quantity if one of the objects included in the other array but can't figure out a way to push the rest of the objects to one another.
Here is how I combined the quantities of matching _id from array1 to productId in array2
if (array1.length > 0) {
for (let i = 0; i < array2.length; i++) {
for (let k = 0; k < array1.length; k++) {
if (array2[i].productid._id === array1[k]._id) {
array1[k].quantity = array1[k].quantity + array2[i].quantity
array2[i].quantity = array1[k].quantity
}
}
}
}
Expected result based on example above:
array1 = [
{
_id: '5eaf8eeac436dbc9b7d75f35',
name: 'Strawberry',
category: 'organic',
image: '/productImages/australian.jpg',
price: '9.65',
quantity: 4
},
{
_id: '5eaf8f61c436dbc9b7d75f36',
name: 'Organic Wild Blue Berry',
category: 'organic',
image: '/productImages/owbb.jpg',
price: '12.50',
quantity: 4
},
{
_id: '5eb0ac47d98c817d9a82df82',
name: 'Mango',
category: 'australian',
image: '/productImages/australian.jpg',
price: '12.25',
quantity: 1
},
{
_id: '5eb0ac71d98c817d9a82df83',
name: 'Peas',
category: 'conventional',
image: '/productImages/owbb.jpg',
price: '25.12',
quantity: 1
}
]
array2 = [
{
_id: '5ec00539f7ff70566fd8a557',
productid: {
_id: '5eaf8eeac436dbc9b7d75f35',
name: 'Strawberry',
category: 'organic',
image: '/productImages/australian.jpg',
price: '9.65'
},
quantity: 4
},
{
_id: '5ec00539f7ff70566fd8a558',
productid: {
_id: '5eaf8f61c436dbc9b7d75f36',
name: 'Organic Wild Blue Berry',
category: 'organic',
image: '/productImages/owbb.jpg',
price: '12.50'
},
quantity: 4
},
{
_id: 'auto-generated-id',
productid: {
_id: '5eb0ac47d98c817d9a82df82',
name: 'Mango',
category: 'australian',
image: '/productImages/australian.jpg',
price: '12.25'
},
quantity: 1
},
{
_id: 'auto-generated-id',
productid: {
_id: '5eb0ac71d98c817d9a82df83',
name: 'Peas',
category: 'conventional',
image: '/productImages/owbb.jpg',
price: '25.12'
},
quantity: 1
}
]
You can do this with reduce function. Here is my try:
var array1 =[{"_id":"5eaf8eeac436dbc9b7d75f35","name":"Strawberry","category":"organic","image":"/productImages/australian.jpg","price":"9.65","quantity":1},{"_id":"5eaf8f61c436dbc9b7d75f36","name":"Organic Wild Blue Berry","category":"organic","image":"/productImages/owbb.jpg","price":"12.50","quantity":1},{"_id":"5eb0ac47d98c817d9a82df82","name":"Mango","category":"australian","image":"/productImages/australian.jpg","price":"12.25","quantity":1},{"_id":"5eb0ac71d98c817d9a82df83","name":"Peas","category":"conventional","image":"/productImages/owbb.jpg","price":"25.12","quantity":1}];
var array2=[ { _id: '5ec00539f7ff70566fd8a557', productid: { _id: '5eaf8eeac436dbc9b7d75f35', name: 'Strawberry', category: 'organic', image: '/productImages/australian.jpg', price: '9.65', }, quantity: 3 }, { _id: '5ec00539f7ff70566fd8a558', productid: { _id: '5eaf8f61c436dbc9b7d75f36', name: 'Organic Wild Blue Berry', category: 'organic', image: '/productImages/owbb.jpg', price: '12.50', }, quantity: 3 }];
result = array1.reduce((acc, elem, i)=>{
index = array2.findIndex(val=>val.productid._id == elem._id);
if(index!=-1) {
array2[index].quantity = elem.quantity += array2[index].quantity;
} else {
array2.push({_id:'some_id'+i, productid: elem, quantity: elem.quantity})
}
acc.push(elem);
return acc;
},[]);
result = [...result, ...array2.filter(elem=> !array1.some(val=>val._id == elem.productid._id)).map(({productid, quantity})=>({...productid, quantity}))];
console.log(result);
console.log(array2)
I would add the quantities of the first array to the second, then regenerate the second array based on the first:
// Create a lookup table to make the whole thing O(n)
const entryById = {};
for(const item of array2)
entryById[item.productid._id] = item;
// Update array2 with the amount of array1
for(const item of array1) {
if(entryById[item]) {
entryById[item].amount += item.amount;
} else {
array2.push(entryById[item] = {
_id: 'generated',
productid: item,
amount: item.amount,
});
}
}
// Regenerate array1
array1 = array2.map(({ productid, amount }) => ({ ...productid, amount }));
I find it strange though that you maintain two different datastructures here.
You could take a hash table for the second array and iterate the first and push a new data set and update the values.
let array1 = [{ _id: "5eaf8eeac436dbc9b7d75f35", name: "Strawberry", category: "organic", image: "/productImages/australian.jpg", price: "9.65", quantity: 1 }, { _id: "5eaf8f61c436dbc9b7d75f36", name: "Organic Wild Blue Berry", category: "organic", image: "/productImages/owbb.jpg", price: "12.50", quantity: 1 }, { _id: "5eb0ac47d98c817d9a82df82", name: "Mango", category: "australian", image: "/productImages/australian.jpg", price: "12.25", quantity: 1 }, { _id: "5eb0ac71d98c817d9a82df83", name: "Peas", category: "conventional", image: "/productImages/owbb.jpg", price: "25.12", quantity: 1 }],
array2 = [{ _id: '5ec00539f7ff70566fd8a557', productid: { _id: '5eaf8eeac436dbc9b7d75f35', name: 'Strawberry', category: 'organic', image: '/productImages/australian.jpg', price: '9.65', }, quantity: 3 }, { _id: '5ec00539f7ff70566fd8a558', productid: { _id: '5eaf8f61c436dbc9b7d75f36', name: 'Organic Wild Blue Berry', category: 'organic', image: '/productImages/owbb.jpg', price: '12.50', }, quantity: 3 }],
ids = array2.reduce((r, o) => {
r[o.productid._id] = o; return r;
}, {}),
result = array1.forEach(o => {
if (ids[o._id]) {
const value = o.quantity;
o.quantity += ids[o._id].quantity;
ids[o._id].quantity += value;
} else {
const { quantity, ...productid } = o;
array2.push(ids[productid._id] = { _id: 'auto-generated-id', productid, quantity });
}
});
console.log(array1);
console.log(array2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
i need to concat all the 'externalId'(inside prod obj) + "id" (inside sup array) + "name" (inside product obj). What would be the best way to do that? I've tried with map and reduce but I wasn't successful. Any help will be appreciated.
const jsonResultKeys = ['AAA', 'BBB', 'CCC']
const items = [];
jsonResultKeys.forEach(k => {
const item = Jsonresult.items[k];
items.push({
description: item.product.name + ':' + item.product.sup[0] + ':'+ item.product.sup[0].prod.externalId ,
})
});
the output expected for this example:
[
{ description: '4444:2:product1'},
{ description: '3333:2:product2'},
{ description: '2222:1:product3'}
]
the json object:
const Jsonresult = {
items: {
'AAA': {
createdAt: '2021-02-11T17:25:22.960-03:00',
product: {
sup: [{
prod: {
externalId: **4444**
},
id: **2**
}],
name: "**product 1**"
},
total: 9.84,
quantity: 1,
price: 15,
updatedAt: '2021-02-11T17:25:22.960-03:00'
},
'BBB': {
createdAt: '2021-02-11T17:25:22.960-03:00',
product: {
sup: [{
prod: {
externalId: **3333**
},
id: **2**
}],
name: "**product 2**"
},
total: 9.84,
quantity: 1,
price: 15,
updatedAt: '2021-02-11T17:25:22.960-03:00'
},
'CCC': {
createdAt: '2021-02-11T17:25:22.960-03:00',
product: {
sup: [{
prod: {
externalId: **2222**
},
id: **1**
}],
name: "**product 3**"
},
}
},
}
The Array#map() method is the most logical method to use - see #MichaelMano's solution - but if you have to use .push() to populate items (const) then stick with .forEach() as follows:
Object.values( Jsonresult.items ).forEach(item => {
items.push( {description: `${item.product.sup[0].prod.externalId}:${item.product.sup[0].id}:${item.product.name}`} );
});
DEMO
const items = [];
const Jsonresult = {
items: {
'AAA': {
createdAt: '2021-02-11T17:25:22.960-03:00',
product: {
sup: [{
prod: {
externalId: 4444
},
id: 2
}],
name: "product 1"
},
total: 9.84,
quantity: 1,
price: 15,
updatedAt: '2021-02-11T17:25:22.960-03:00'
},
'BBB': {
createdAt: '2021-02-11T17:25:22.960-03:00',
product: {
sup: [{
prod: {
externalId: 3333
},
id: 2
}],
name: "product 2"
},
total: 9.84,
quantity: 1,
price: 15,
updatedAt: '2021-02-11T17:25:22.960-03:00'
},
'CCC': {
createdAt: '2021-02-11T17:25:22.960-03:00',
product: {
sup: [{
prod: {
externalId: 2222
},
id: 1
}],
name: "product 3"
},
}
},
};
Object.values( Jsonresult.items ).forEach(item => {
items.push( {description: `${item.product.sup[0].prod.externalId}:${item.product.sup[0].id}:${item.product.name}`} );
});
console.log( items );
You could do the following, Map over the results and return an object, this will create an array of objects.
You wont even need the keys.
const map = Object.values(Jsonresult.items).map((item) => {
return {
description: `${item.product.sup[0].prod.externalId}:${item.product.sup[0].id}:${item.product.name}`,
};
});
[
{ description: '4444:2:product 1' },
{ description: '3333:2:product 2' },
{ description: '2222:1:product 3' }
]
I want the result to sum all the quantity of same cat.
var data = [
{ cat: 'EK-1',name:"test",info:"mat", quantity: 3},
{ cat: 'EK-2', name:"test2",info:"nat"quantity: 1}
];
I have array of object having some similar objects. How to add quantity and create unique object? This is what I tried.
var data = [{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-2',
name: "test2",
info: "nat",
quantity: 1
}
];
const products = Array.from(data.reduce((acc, {
cat,
quantity
}) =>
acc.set(cat, (acc.get(cat) || 0) + quantity),
new Map()
), ([cat, quantity]) => ({
cat,
quantitya
}));
console.log(products);
You first group and sum quantities under categories keys, using reduce and then you discard those keys with Object.values.
var data = [{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-2',
name: "test2",
info: "nat",
quantity: 1
}];
const result = Object.values(data.reduce((acc, item) => {
if (!acc[item.cat]) {
acc[item.cat] = item;
} else {
acc[item.cat] = { ...item, quantity: item.quantity + acc[item.cat].quantity }
}
return acc;
}, {}))
console.log(result)
You could get the complete object as value for the map and increment quantity.
const
data = [{ cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-2', name: "test2", info: "nat", quantity: 1 }],
products = Array.from(
data
.reduce(
(acc, o) => acc.set(o.cat, { ...o, quantity: (acc.get(o.cat)?.quantity || 0) + o.quantity }),
new Map
)
.values()
);
console.log(products);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'm building a shop system, so when a customer orders some items and tries to save them to the database, I want to subtract the preview product qty from the new qty ordered.
My API is sending that cart items
const cartItems = [
{
_id: 1,
name: 'item one',
price: 12.99,
qty: 6,
},
{
_id: 3,
name: 'item three',
price: 9.99,
qty: 10,
},
{
_id: 2,
name: 'item two',
price: 6.99,
qty: 2,
},
]
And my MongoDB return this value, so how do I substract stock number from qty?
const products = await Product.find({})
[
{
_id: 1,
name: 'item one',
price: 12.99,
stock: 14,
},
{
_id: 2,
name: 'item two',
price: 6.99,
stock: 78,
},
{
_id: 3,
name: 'item three',
price: 9.99,
stock: 54,
},
]
I want to get a result like this:
[
{
_id: 1,
name: 'item one',
price: 12.99,
stock: 8,
},
{
_id: 2,
name: 'item two',
price: 6.99,
stock: 76,
},
{
_id: 3,
name: 'item three',
price: 9.99,
stock: 44,
},
]
Seems a naive double nested loop could be sufficient for iterating both arrays and computing a new products array.
const newProducts = products.map((product) => ({
...product,
stock:
product.stock -
(cartItems.find((item) => item._id === product._id)?.qty || 0)
}));
const cartItems = [
{
_id: 1,
name: "item one",
price: 12.99,
qty: 6
},
{
_id: 3,
name: "item three",
price: 9.99,
qty: 10
},
{
_id: 2,
name: "item two",
price: 6.99,
qty: 2
}
];
const products = [
{
_id: 1,
name: "item one",
price: 12.99,
stock: 14
},
{
_id: 2,
name: "item two",
price: 6.99,
stock: 78
},
{
_id: 3,
name: "item three",
price: 9.99,
stock: 54
}
];
const newProducts = products.map((product) => ({
...product,
stock:
product.stock -
(cartItems.find((item) => item._id === product._id)?.qty || 0)
}));
console.log(newProducts);
A more optimal method would be to precompute a map of quantities by id for O(1) lookups for an overall O(n) runtime complexity (as opposed to the O(n^2) of the double-nested loop above).
const quantityMap = cartItems.reduce(
(quantities, { _id, qty }) => ({
...quantities,
[_id]: qty || 0
}),
{}
);
const newProducts = products.map((product) => ({
...product,
stock: product.stock - (quantityMap[product._id] || 0)
}));
const cartItems = [
{
_id: 1,
name: "item one",
price: 12.99,
qty: 6
},
{
_id: 3,
name: "item three",
price: 9.99,
qty: 10
},
{
_id: 2,
name: "item two",
price: 6.99,
qty: 2
}
];
const products = [
{
_id: 1,
name: "item one",
price: 12.99,
stock: 14
},
{
_id: 2,
name: "item two",
price: 6.99,
stock: 78
},
{
_id: 3,
name: "item three",
price: 9.99,
stock: 54
}
];
const quantityMap = cartItems.reduce(
(quantities, { _id, qty }) => ({
...quantities,
[_id]: qty || 0
}),
{}
);
const newProducts = products.map((product) => ({
...product,
stock: product.stock - (quantityMap[product._id] || 0)
}));
console.log(newProducts);
I am trying pushing the name but in the console log I see just a number and not the actual name
What am i doing wrong??
const cartItems = [{
id: 1,
name: "Soup",
price: 3,
category: "starters",
count: 1
},
{
id: 2,
name: "Pâté",
price: 5,
category: "starters",
count: 1
},
{
id: 9,
name: "Sticky toffee",
price: 18,
category: "desserts",
count: 1
}
]
var dishesArray = [];
var groupByCategory = []
cartItems.reduce(function(res, value) {
if (!res[value.category]) {
res[value.category] = {
category: value.category,
count: 0,
dishes: dishesArray.push(value.name), // problem here
};
groupByCategory.push(res[value.category]);
}
res[value.category].count += value.count;
return res;
}, {});
console.log(groupByCategory)
Expected output
[{category: "starters", count: 2, dishes:["Soup","Pâté"]},
{category: "desserts", count: 1, dishes:["Sticky toffee"]}]
As mentioned, a push returns an int
I believe you are looking for this much shortened reduce
const cartItems = [
{ id: 1, name: "Soup", price: 3, category: "starters", count: 1 },
{ id: 2, name: "Pâté", price: 5, category: "starters", count: 1 },
{ id: 9, name: "Sticky toffee", price: 18, category: "desserts", count: 1}
];
const groupByCategory = cartItems.reduce(function(res, value) {
const cat = value.category;
res[cat] = res[cat] || { category: cat, count: 0, dishes: [] };
res[cat].count += value.count;
res[cat].dishes.push(value.name)
return res;
}, {});
console.log(groupByCategory)
I'm trying to get an array of names of objects that have options.amount all equals to zero. Thanks for your time. This is what i tryed:
let variants = [
{
name: 'extra',
options: [
{
name: 'meat',
price: 3,
amount: 0
},
{
name: 'cheese',
price: 1,
amount: 0
}
]
},
{
name: 'sauce',
options: [
{
name: 'ketchup',
price: 2,
amount: 1
},
{
name: 'mayo',
price: 1,
amount: 0
}
]
}
];
//Expected output = ['extra']
let arrayOfOptionsNames = variants.map(x => x.options.filter(y => y.amount === 0 ? x.name : 0))
console.log(arrayOfOptionsNames)
You could use Array.prototype.filter() and Array.prototype.every() method to get your result. Every method test if every elements of the array pass the test by the given callback function and returns a boolean value.
const variants = [
{
name: 'extra',
options: [
{
name: 'meat',
price: 3,
amount: 0,
},
{
name: 'cheese',
price: 1,
amount: 0,
},
],
},
{
name: 'sauce',
options: [
{
name: 'ketchup',
price: 2,
amount: 1,
},
{
name: 'mayo',
price: 1,
amount: 0,
},
],
},
];
const ret = variants
.filter((x) => x.options.every((y) => y.amount === 0))
.map((x) => x.name);
console.log(ret);
You could filter and get the wanted property.
let variants = [{ name: 'extra', options: [{ name: 'meat', price: 3, amount: 0 }, { name: 'cheese', price: 1, amount: 0 }] }, { name: 'sauce', options: [{ name: 'ketchup', price: 2, amount: 1 }, { name: 'mayo', price: 1, amount: 0 }] }],
result = variants
.filter(({ options }) => options.every(({ amount }) => !amount))
.map(({ name }) => name);
console.log(result);