Find index of object array - javascript

I'm stuck with the code. I actually want to find the index of elements in dataLayer using typescript/javascript.
track: { products },
dataLayers: { current: { cart: { items } } }
products?: IProduct[]
export interface IProduct {
id: string
quantity?: string
name?: string
}
items?: ICartItem[]
export interface ICartItem {
id: string
brand: string
name: string
quantity: number
}
track: { products }
products have {id,quantity}
dataLayers: { current: { cart: { items } } }
items have {id, brand, name, quantity }
Now I want to find the position/index of products, For Example:
Example: *
products:{
[{id: 'a123',quantity: '1'},{id:'a345', quantity:'2'}]
}
items:{
[{id: 'a123',brand:'pen',name: 'Reynolds', quantity: '1'}, {id: 'a143',brand:'pencil',name: 'Nataraj', quantity: '3'}, {id: 'a122',brand:'pen',name: 'Parker',quantity: '1'},{id:'a345',brand:'Eraser',name: 'Faber-Castell', quantity:'2'}]
}
position of {id: 'a123',quantity: '1'} should be 1 and position of {id:'a345', quantity:'2'} should be 4
My code looks like below:
I have used map to get id from products as shown
const id = products.map(product => { return product.id})
now I want to find index/position of those products in items.so I tried like below
let position = filter((item: ICartItem) => {
if(id.includes(item.id)){
return {id}
}
}).findindex(id)
i.e.,
const id = products.map(product => { return product.id})
let position = filter((item: ICartItem) => {
if(id.includes(item.id)){
return {id}
}
}).findindex(id)
but I getting error
Argument of type 'string[]' is not assignable to parameter of type '(value: ICartItem, index: number, obj: ICartItem[]) => unknown'.
Type 'string[]' provides no match for the signature '(value: ICartItem, index: number, obj: ICartItem[]): unknown'.ts(2345)
an Some help me in finding position/index of the filtered product?

After map you can chain .indexOf() to get the Index of the object and Index of a345 would be 3 not 4 because indexes are zero based in an array
let items = [{
id: 'a123',
brand: 'pen',
name: 'Reynolds',
quantity: '1'
}, {
id: 'a143',
brand: 'pencil',
name: 'Nataraj',
quantity: '3'
}, {
id: 'a122',
brand: 'pen',
name: 'Parker',
quantity: '1'
}, {
id: 'a345',
brand: 'Eraser',
name: 'Faber-Castell',
quantity: '2'
}]
let index= items.map(function(e) {
return e.id;
}).indexOf('a345')
console.log(`Index=${index}`)
console.log(`position= ${index+1}`)

You can chain map and indexOf to get result as an array with positions.
const products = [
{ id: 'a123', quantity: '1' },
{ id: 'a345', quantity: '2' },
];
const items = [
{ id: 'a123', brand: 'pen', name: 'Reynolds', quantity: '1' },
{ id: 'a143', brand: 'pencil', name: 'Nataraj', quantity: '3' },
{ id: 'a122', brand: 'pen', name: 'Parker', quantity: '1' },
{ id: 'a345', brand: 'Eraser', name: 'Faber-Castell', quantity: '2' },
];
const result = products.map(product => items.map(item => item.id).indexOf(product.id) + 1);
console.log(result)
If array with positions needs to return id as well then you can do:
const products = [
{ id: 'a123', quantity: '1' },
{ id: 'a345', quantity: '2' },
];
const items = [
{ id: 'a123', brand: 'pen', name: 'Reynolds', quantity: '1' },
{ id: 'a143', brand: 'pencil', name: 'Nataraj', quantity: '3' },
{ id: 'a122', brand: 'pen', name: 'Parker', quantity: '1' },
{ id: 'a345', brand: 'Eraser', name: 'Faber-Castell', quantity: '2' },
];
const result = products.map(product => {
const id = product.id;
return {
id,
position: items.map(item => item.id).indexOf(id) + 1
}
});
console.log(result)

You can try:
const ids = products.map( product => product.id);
const positions = items.map( ( item, i ) => {
if( ids.includes(item.id)){
return{
position: i + 1,
id: item.id
}
}
return null
}).filter(Boolean)
//[ { position: 1, id: 'a123' }, { position: 4, id: 'a345' } ]

Related

Filtering array based on selected object in JS

Trying to get the filtered array based on the selected object. How can I loop through damaged array which is inside the object and get the resultant array? I tried to add another condition using .map but it prints the rest of the items as well.
Below is the snippet
const inventory = [{
name: 'Jeep',
id: '100',
damaged: [{
name: 'Wrangler',
id: '200'
},
{
name: 'Sahara',
id: '201'
}
]
}, {
name: 'Audi',
id: '101',
damaged: [{
name: 'Q3',
id: '300'
}]
}]
const purchasedCars = [{
car: 'Jeep',
id: '100'
}, {
car: 'Jeep - Wrangler',
id: '200',
},
{
car: 'Jeep - Sahara',
id: '201'
},
{
car: 'Audi - Q3',
id: '300'
}
]
const selectedCar = purchasedCars[0];
const filterCars = () => {
const result = purchasedCars.filter((inv) => inv.id === selectedCar.id)
console.log('result -->', result);
}
filterCars();
Expected output is
[{
car: 'Jeep',
id: '100'
},
{
car: 'Jeep - Wrangler',
id: '200',
},
{
car: 'Jeep - Sahara',
id: '201'
}]
Could anyone please help?
Trying to read your mind here. Is this what you want?
const inventory = [{
name: 'Jeep',
id: '100',
damaged: [{
name: 'Wrangler',
id: '200'
},
{
name: 'Sahara',
id: '201'
}
]
}, {
name: 'Audi',
id: '101',
damaged: [{
name: 'Q3',
id: '300'
}]
}]
const purchasedCars = [{
car: 'Jeep',
id: '100'
}, {
car: 'Jeep - Wrangler',
id: '200',
},
{
car: 'Jeep - Sahara',
id: '201'
},
{
car: 'Audi - Q3',
id: '300'
}
]
const selectedCar = purchasedCars[0];
const filterCars = () => {
let result;
const parentItem = inventory.filter((inv) => inv.id === selectedCar.id)[0];
if ("damaged" in parentItem) {
result = [selectedCar, ...(parentItem.damaged)];
}
console.log('result -->', result);
}
filterCars();
Note that if you can have more nested car types in the damaged property you would you to call filterCars recursively and pass in the car object. If you also want to filters items that may also be present in the damaged property, then you would first need to use the flatMap method (before the filter).

add qty for similar json objects in javascript

I want the result to be summing all the qty of same cat.
var data = [
{ cat: 'EK-1',name:"test",info:"mat", quantity: 3},
{ cat: 'EK-2', name:"test2",info:"nat"quantity: 1}
];
I tried like this below i have array of object having some similar objects. how to add qty and create unque objects .below i have given 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,
quantity
}));
console.log(products);
You can do this using Array#reduce, using the accumulator to pass on the new object:
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, }, ];
let seen = [];
const res = data.reduce((acc, { cat, ...rest }) => {
const idx = seen.indexOf(cat);
if (idx == -1) (acc.push({cat, ...rest}), seen.push(cat));
else acc[idx].quantity++;
return acc;
}, []);
console.log(res);

How do I get the total sum of nested arrays in Reactjs?

I want to get the total price of nested arrays in a specific category e.g: Hot Drinks.
Here is a sample of what I have now, so I want to filter out and get the total price of Hot Drinks Category only.
[
{
totalPrice: 30,
_id: '6014fa4324e125599eaa72b5',
orderItems: [
{
_id: '6014fa4324e125599eaa747ss',
category: 'Breakfast',
name: 'food name 1',
price: 3,
qty: 1,
},
{
_id: '6014fa4324e125599eaa747s5',
category: 'Hot Drinks',
name: 'drink name 1',
price: 3,
qty: 5,
},
{
_id: '6014fa4324e125599eaa74767',
category: 'Hot Drinks',
name: 'drink name 2',
price: 4,
qty: 2,
},
],
},
{
totalPrice: 23,
_id: '6014fa4324e125599eaa7276e',
orderItems: [
{
_id: '6014fa4324e125599eaa747ss',
category: 'Hot Drinks',
name: 'drink name 1',
price: 3,
qty: 6,
},
],
},
]
You can apply a filter method on the array and then just add the values on the filtered array. Something like below:
let prod = [
{
totalPrice: 30,
_id: '6014fa4324e125599eaa72b5',
orderItems: [
{
_id: '6014fa4324e125599eaa747ss',
category: 'Breakfast',
name: 'food name 1',
price: 3,
qty: 1,
},
{
_id: '6014fa4324e125599eaa747s5',
category: 'Hot Drinks',
name: 'drink name 1',
price: 3,
qty: 5,
},
{
_id: '6014fa4324e125599eaa74767',
category: 'Hot Drinks',
name: 'drink name 2',
price: 4,
qty: 2,
},
],
},
{
totalPrice: 23,
_id: '6014fa4324e125599eaa7276e',
orderItems: [
{
_id: '6014fa4324e125599eaa747ss',
category: 'Hot Drinks',
name: 'drink name 1',
price: 3,
qty: 6,
},
],
},
];
function getPriceByCategory(category, products) {
let price = 0;
products.forEach(orders => {
orders.orderItems.filter(order => order.category == category).forEach(item => {
price += item.price;
});
});
return price;
}
const totalPrice = getPriceByCategory('Hot Drinks', prod);
alert(totalPrice);
Sample JS Fiddle: https://jsfiddle.net/sagarag05/qwzju53f/9/
const filterBy = 'Hot Drinks';
const items = [
{
totalPrice: 30,
_id: '6014fa4324e125599eaa72b5',
orderItems: [
{
_id: '6014fa4324e125599eaa747ss',
category: 'Breakfast',
name: 'food name 1',
price: 3,
qty: 1,
},
{
_id: '6014fa4324e125599eaa747s5',
category: 'Hot Drinks',
name: 'drink name 1',
price: 3,
qty: 5,
},
{
_id: '6014fa4324e125599eaa74767',
category: 'Hot Drinks',
name: 'drink name 2',
price: 4,
qty: 2,
},
],
},
{
totalPrice: 23,
_id: '6014fa4324e125599eaa7276e',
orderItems: [
{
_id: '6014fa4324e125599eaa747ss',
category: 'Hot Drinks',
name: 'drink name 1',
price: 3,
qty: 6,
},
],
},
]
const sumOf = (items, filterBy) => {
let totalPrice = 0;
items.forEach(item => {
item.orderItems.forEach(orderItem => {
if (orderItem.category === filterBy) {
totalPrice += orderItem.price;
}
})
})
return totalPrice;
}
console.log(sumOf(items, filterBy))
let sum = 0;
allOrders.forEach(order => {
order.orderItems.forEach(item => {
if(item.category=='Hot Drinks') {
sum+ = item.price * item.qty
}});
});
sum has the total price for Hot Drinks
Assuming you named that information as data:
Generate a big array of all the "orderItems"
For each of those elements sum the price if the category is "Hot Drinks"
const totalPrice = data
.reduce((acc, { orderItems }) => [...acc, ...orderItems], [])
.reduce((acc, { category, price }) => category === "Hot Drinks" ? acc + price : acc, 0);
console.log(totalPrice); // 10
Use flatMap and reduce or alternatively using forEach and destructuring
const total = (arr, text) =>
arr
.flatMap(({ orderItems }) => orderItems)
.reduce((acc, { category, price }) =>
(acc + (category === text ? price : 0)), 0);
// alternatively
const total2 = (arr, text, acc = 0) => {
arr.forEach(({ orderItems }) =>
orderItems.forEach(
({ category, price }) => (category === text && (acc += price))
)
);
return acc;
};
const data = [
{
totalPrice: 30,
_id: "6014fa4324e125599eaa72b5",
orderItems: [
{
_id: "6014fa4324e125599eaa747ss",
category: "Breakfast",
name: "food name 1",
price: 3,
qty: 1,
},
{
_id: "6014fa4324e125599eaa747s5",
category: "Hot Drinks",
name: "drink name 1",
price: 3,
qty: 5,
},
{
_id: "6014fa4324e125599eaa74767",
category: "Hot Drinks",
name: "drink name 2",
price: 4,
qty: 2,
},
],
},
{
totalPrice: 23,
_id: "6014fa4324e125599eaa7276e",
orderItems: [
{
_id: "6014fa4324e125599eaa747ss",
category: "Hot Drinks",
name: "drink name 1",
price: 3,
qty: 6,
},
],
},
];
console.log(total(data, 'Hot Drinks'))
console.log(total2(data, 'Hot Drinks'))

Lodash Merge Two Arrays and categorize it

i neeed to merge two arrays: Categories and Products. Each product has a category object. I need to organize by category, include the category object and keep the empty categories. GroupBy function include only one parameter.
const Categories= [
{id: 1, 'name': 'category1'}
{id: 2, 'name': 'category2'},
{id: 3, 'name': 'category3'},
{id: 4, 'name': 'category4'},
]
const Products= [
{id: 1, 'name': 'product1', category: {id: 1, name: 'category1'}},
{id: 2, 'name': 'product2', category: {id: 1, name: 'category1'}},
{id: 3, 'name': 'product3', category: {id: 2, name: 'category2'}},
{id: 4, 'name': 'product4', category: {id: 2, name: 'category2'}},
]
expected result
const result = [
{
category: {id: 1, name: 'category1'},
products:[{id:1, name: 'produt1'}, {id: 2, name: 'produto1'} ]
},
{
category: {id: 2, name: 'category2'},
products:[{id:3, name: 'produt3'}, {id: 4, name: 'produto4'} ]
},
{
category: {id: 3, name: 'category3'},
products:[]
},
{
category: {id: 4, name: 'category4'},
products:[]
},
]
attempts:
for (i = 0; i < categoriesJson.length; i++) {
categoriesJson[i] = _.assign({}, categoriesJson[i], { products: [] })
for (j = 0; j < productsJson.length; j++) {
if(productsJson[j].categoryId.objectId === categoriesJson[i].objectId){
categoriesJson[i].products.push(productsJson[j])
}
}
}
Concat the Categories (formatted by to a Product format) to the Products, group by the category.id, and then map each group - category is taken from the 1st item, while products are the the items in groups, without the category, and empty items are rejected:
const Products = [{"id":1,"name":"product1","category":{"id":1,"name":"category1"}},{"id":2,"name":"product2","category":{"id":1,"name":"category1"}},{"id":3,"name":"product3","category":{"id":2,"name":"category2"}},{"id":4,"name":"product4","category":{"id":2,"name":"category2"}}]
const Categories = [{"id":1,"name":"category1"},{"id":2,"name":"category2"},{"id":3,"name":"category3"},{"id":4,"name":"category4"}]
const result = _(Products)
.concat(Categories.map(category => ({ category })))
.groupBy('category.id')
.map(group => ({
category: _.head(group).category,
products: _(group)
.map(o => _.omit(o, 'category'))
.reject(_.isEmpty)
.value()
}))
.value()
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
And the same idea with lodash/fp. Wrap the _.flow() with the _.useWith() function, and preformat the Categories (2nd param) to fit the Categories. The rest is similar to the lodash chain.
const { useWith, identity, flow, concat, groupBy, map, head, omit, reject, isEmpty } = _
const formatProducts = flow(map(omit('category')), reject(isEmpty))
const fn = useWith(flow(
concat,
groupBy('category.id'),
map(group => ({
category: head(group).category,
products: formatProducts(group)
}))
), [identity, map(category => ({ category }))])
const Products = [{"id":1,"name":"product1","category":{"id":1,"name":"category1"}},{"id":2,"name":"product2","category":{"id":1,"name":"category1"}},{"id":3,"name":"product3","category":{"id":2,"name":"category2"}},{"id":4,"name":"product4","category":{"id":2,"name":"category2"}}]
const Categories = [{"id":1,"name":"category1"},{"id":2,"name":"category2"},{"id":3,"name":"category3"},{"id":4,"name":"category4"}]
const result = fn(Products, Categories)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
If lodash is not a requirement in the solution, this is how I did it with plain javascript;
const Categories= [
{id: 1, 'name': 'category1'},
{id: 2, 'name': 'category2'},
{id: 3, 'name': 'category3'},
{id: 4, 'name': 'category4'}
];
const Products= [
{id: 1, 'name': 'product1', category: {id: 1, name: 'category1'}},
{id: 2, 'name': 'product2', category: {id: 1, name: 'category1'}},
{id: 3, 'name': 'product3', category: {id: 2, name: 'category2'}},
{id: 4, 'name': 'product4', category: {id: 2, name: 'category2'}},
];
const result = [];
for (let index in Categories) {
let category_id = Categories[index].id;
result.push({
category: Categories[index],
products: GetProductsWithCategoryId(category_id)
});
}
function GetProductsWithCategoryId(category_id) {
let products = [];
for (let index in Products) {
if (Products[index].category.id == category_id) {
products.push({
id: Products[index].id,
name: Products[index].name
});
}
}
return products;
}
console.log("result:", result);
Using reduce, create a mappedProducts object which groups the Products based on the category.id. Like this:
{
"1": [{ id: 1, name: "product1" }, { id: 2, name: "product2" }],
"2": [{ id: 3, name: "product3" }, { id: 4, name: "product4" }]
}
Then, map the Categories array and get the output for each category
const Categories=[{id:1,name:"category1"},{id:2,name:"category2"},{id:3,name:"category3"},{id:4,name:"category4"},],
Products=[{id:1,name:"product1",category:{id:1,name:"category1"}},{id:2,name:"product2",category:{id:1,name:"category1"}},{id:3,name:"product3",category:{id:2,name:"category2"}},{id:4,name:"product4",category:{id:2,name:"category2"}}];
const mappedProducts = Products.reduce((acc, { category, ...rest }) => {
acc[category.id] = acc[category.id] || [];
acc[category.id].push(rest)
return acc;
}, {})
const output = Categories.map(category => ({
category,
products: mappedProducts[category.id] || []
}))
console.log(output)
In a single function. Lodash is not necessary:
const Categories = [
{ id: 1, name: "category1" },
{ id: 2, name: "category2" },
{ id: 3, name: "category3" },
{ id: 4, name: "category4" }
];
const Products = [
{ id: 1, name: "product1", category: { id: 1, name: "category1" } },
{ id: 2, name: "product2", category: { id: 1, name: "category1" } },
{ id: 3, name: "product3", category: { id: 2, name: "category2" } },
{ id: 4, name: "product4", category: { id: 2, name: "category2" } }
];
function combine(categories, products) {
return categories.reduce((list, category) => {
const nextItem = {
category,
products: [
products.filter(p => p.category.id === category.id).map(
({ id, name }) => ({
id,
name
})
)
]
};
list.push(nextItem);
return list;
}, []);
}
const result = combine(Categories, Products)
Now for your information, if you had a huge list of categories and/or products, this wouldn't be the ideal solution as there is a lot of looping involved. Instead, you would cache products in such a way that you only ever need to look at a given product once (rather than looking at every product for every category). With a small data set, this optimization isn't necessary.

How to combine duplicate object value in the array then output a list?

I've been working on this couple hours and google around, see lots of example for remove duplicate, but not combined the value. so I hope someone can help me out here.
I want to check the item.name is the same, then add the price together then push to new list array.
const items = [
{ name: 'apple', price: '10' },
{ name: 'banana', price: '1' },
{ name: 'orange', price: '2' },
{ name: 'apple', price: '5' },
{ name: 'orange', price: '2.5' },
{ name: 'banana', price: '3' },
{ name: 'strawberry', price: '7' },
{ name: 'apple', price: '12' }
]
let newItem = []
const checkItem = items.map((prev, next) => {
if (prev.name === next.name) {
return newItem.push = {
name: next.name,
value: parseInt(prev.price) + parseInt(next.price)
}
}
});
console.log(newItem)
Big thanks for the help!
This will work.You can use reduce with Find.
const items = [{
name: 'apple',
price: '10'
},
{
name: 'banana',
price: '1'
},
{
name: 'orange',
price: '2'
},
{
name: 'apple',
price: '5'
},
{
name: 'orange',
price: '2.5'
},
{
name: 'banana',
price: '3'
},
{
name: 'strawberry',
price: '7'
},
{
name: 'apple',
price: '12'
}
]
let result = items.reduce((acc, el) => {
if (acc.filter(ele => ele.name == el.name).length == 0) {
acc.push(el);
} else {
let filtered = acc.find(ele => ele.name == el.name)
filtered.price = parseFloat(filtered.price) + parseFloat(el.price);
}
return acc;
}, [])
console.log(result)
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
The Array​.prototype​.map()'s callback functions first two arguments are currentValue i.e item of the array and second value is it's index, & not prev and next elements.
What you are looking for is something like this.
const items = [
{ name: "apple", price: "10" },
{ name: "banana", price: "1" },
{ name: "orange", price: "2" },
{ name: "apple", price: "5" },
{ name: "orange", price: "2.5" },
{ name: "banana", price: "3" },
{ name: "strawberry", price: "7" },
{ name: "apple", price: "12" }
];
const combine = items.reduce((acc, item) => {
if (acc[item.name] !== undefined) {
acc[item.name] += Number(item.price);
} else acc[item.name] = Number(item.price);
return acc;
}, {});
const fruitKeys = Object.keys(combine);
newItem = fruitKeys.map(item => ({ name: item, price: combine[item] }));
console.log(newItem);
I have split the solution into two steps, namely combine and reconstruction of the object so that you can clearly see what's happening.
I highly recommend you to refer the documentation for reduce method to understand its working

Categories