Comparing two arrays and adding objects to the other one - javascript

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

concat strings from nested objects arrays

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' }
]

Get quantity in object respective with the category

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; }

How do I update a stock number from cart items qty in Nextjs?

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);

pushing a string into array return a number and not the actual string?

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)

get name of object in array when option.amount equals zero

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);

Categories

Resources