I am trying to get a function to search an array of objects and then return the entire object based on the filter - arrays

I am trying to get my function working and I can not for the life of me figure out why it isnt. I am trying to use .filter() to search the array of objects to find the object with the tag ketchup. Then return the whole object it is in to the console log
let foodArr = [
{
type: 'Chicken',
rating: 1,
tags: ['chicken', 'free-range', 'no hormones'],
price: 10,
popularity: 80
},
{
type: 'pizza',
rating: 5,
tags: ['pepperoni', 'sauce', 'bread'],
price: 25,
popularity: 56
},
{
type: 'hamburger',
rating: 3,
tags: ['bun', 'patty', 'lettuce'],
price: 8,
popularity: 99
},
{
type: 'wings',
rating: 4,
tags: ['wing', 'bbq', 'ranch'],
price: 12,
popularity: 68
},
{
type: 'fries',
rating: 2,
tags: ['ketchup'],
price: 4,
popularity: 100
}
]
const filteredFood = foodArr.filter(function(obj) {
return obj.tags[''] === 'ketchup'
})
console.log(filteredFood)

const filteredFood = foodArr.filter(function(value){
for (let i=0; i<value.tags.length; i++)
if(value.tags[i] === 'ranch'){
return value.tags[i]
}
}
)
console.log(filteredFood)

Related

Mapping through nested arrays in es6 javascript

I have a simple array that I want to group it's objects by date so I used this function
const groupedDates= Object.entries(
items.reduce((acc, { product, price, type, date }) => {
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({ product, price, type date });
return acc;
}, {})
).map(([date, items]) => ({ date, items }));
the array
const items = [
{
id: 1,
product: "milk",
price: 10,
type: "drink"
date: "01/01/2022",
},
{
id: 2,
product: "coca",
price: 11,
type: "drink"
date: "01/01/2022",
},
{
id: 3,
product: "pepsi",
price: 20,
type: "drink"
date: "01/01/2024",
},
{
id: 4,
product: "carrots",
price: 30,
type: "food",
date: "01/01/2023",
},
];
I got this result
{
0: [
date: 01/01/2022,
items : [
0 : {
id: 1,
product: "milk",
price: 10,
type: "drink"
date: "01/01/2022"
}
1 : {
id: 2,
product: "coca",
price: 11,
type: "drink"
date: "01/01/2022",
}
],
1: [
date: "01/01/2024",
items : [
0 : {
id: 3,
product: "pepsi",
price: 20,
type: "drink"
date: "01/01/2024",
}
],
2: [
date: "01/01/2023",
items: [
0:{
id: 4,
product: "carrots",
price: 30,
type: "food",
date: "01/01/2023"
}
]
]
}
Issue:
I cannot seem to figure out how to access items1 when it exists.
What I have tried
is the map below but it only returns the first level of items which is 0 and if I do items1 it returns an error because not all arrays have a second item.
{groupedDates.map((obj) => (
{obj.items[0].product}))}
UPDATE
I'd also like to get the total for each date so I can have a card that has the Date + The total + each item and it's individual price. After getting some help from #Nick, I've managed to output the date, the item and it's price, now I'm still missing the total price for the date.
You need to iterate the items in each obj to get the list of products:
const items = [
{ id: 1, product: "milk", price: 10, type: "drink", date: "01/01/2022" },
{ id: 2, product: "coca", price: 11, type: "drink", date: "01/01/2022" },
{ id: 3, product: "pepsi", price: 20, type: "drink", date: "01/01/2024" },
{ id: 4, product: "carrots", price: 30, type: "food", date: "01/01/2023" },
];
const groupedDates = Object.entries(
items.reduce((acc, { product, price, type, date }) => {
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({ product, price, type, date });
return acc;
}, {})
).map(([date, items]) => ({ date, items }));
const allProducts = groupedDates.map((obj) => obj.items.map(i => i.product))
console.log(allProducts)
const totalsByDate = groupedDates.map(({ date, items }) => (
{ [date] : items.reduce((acc, item) => acc + item.price, 0) }
))
console.log(totalsByDate)
.as-console-wrapper { max-height:100% !important; top 0 }
Note I would make groupedDates an object with its keys being the dates; that will make looking up data for a given date much easier. For example:
const items = [
{ id: 1, product: "milk", price: 10, type: "drink", date: "01/01/2022" },
{ id: 2, product: "coca", price: 11, type: "drink", date: "01/01/2022" },
{ id: 3, product: "pepsi", price: 20, type: "drink", date: "01/01/2024" },
{ id: 4, product: "carrots", price: 30, type: "food", date: "01/01/2023" },
];
const groupedDates = items.reduce((acc, { date, ...rest }) => {
acc[date] = (acc[date] || []).concat({ ...rest })
return acc;
}, {})
console.log(groupedDates)
const allProducts = Object.values(groupedDates)
.flatMap(arr => arr.map(obj => obj.product))
console.log(allProducts)
const totalsByDate = Object.entries(groupedDates).map(([ date, items ]) => (
{ [date] : items.reduce((acc, item) => acc + item.price, 0) }
))
console.log(totalsByDate)
.as-console-wrapper { max-height:100% !important; top 0; }

TypeError: Cannot destructure property 'title' of 'collections' as it is undefined

I am trying to get collections using selectors. Here is my code:
Selectors
import { createSelector } from "reselect";
export const selectShop = state => state.shop;
export const selectCollections = createSelector(
[selectShop],
shop => shop.collections
)
export const selectCollectionForPreview = createSelector(
[selectCollections],
collections => Object.keys(collections).map(key => collections[key])
)
export const selectCollectionItem = collectionUrl =>
createSelector(
[selectCollections],
collections => collections[collectionUrl]
//It seems that the selector above is returning collections as an array instead of object, so collections[collectionUrl] is returning undefined
)
Component
const CollectionPage = ({collections}) => {
// const {title, items} = Object.keys(collections)
const {title, items} = collections
console.log('collection', collections);
return(
// <></>
<div className="collection-page">
<h2 className='title'>{title}</h2>
<div className='items'>
{items.map( item =>
<CollectionItem key={item.id} item={item}/>
)}
</div>
</div>
)
}
const mapStateToProps = (state,ownProps) => ({
collections: selectCollectionItem(ownProps.match.params.collectionId)(state)
})
export default connect(mapStateToProps)(CollectionPage);
SHOP_DATA
const SHOP_DATA = {
hats:{
id: 1,
title: 'Hats',
routeName: 'hats',
items: [
{
id: 1,
name: 'Brown Brim',
imageUrl: 'https://i.ibb.co/ZYW3VTp/brown-brim.png',
price: 25
},
{
id: 2,
name: 'Blue Beanie',
imageUrl: 'https://i.ibb.co/ypkgK0X/blue-beanie.png',
price: 18
},
{
id: 3,
name: 'Brown Cowboy',
imageUrl: 'https://i.ibb.co/QdJwgmp/brown-cowboy.png',
price: 35
},
{
id: 4,
name: 'Grey Brim',
imageUrl: 'https://i.ibb.co/RjBLWxB/grey-brim.png',
price: 25
},
{
id: 5,
name: 'Green Beanie',
imageUrl: 'https://i.ibb.co/YTjW3vF/green-beanie.png',
price: 18
},
{
id: 6,
name: 'Palm Tree Cap',
imageUrl: 'https://i.ibb.co/rKBDvJX/palm-tree-cap.png',
price: 14
},
{
id: 7,
name: 'Red Beanie',
imageUrl: 'https://i.ibb.co/bLB646Z/red-beanie.png',
price: 18
},
{
id: 8,
name: 'Wolf Cap',
imageUrl: 'https://i.ibb.co/1f2nWMM/wolf-cap.png',
price: 14
},
{
id: 9,
name: 'Blue Snapback',
imageUrl: 'https://i.ibb.co/X2VJP2W/blue-snapback.png',
price: 16
}
]
},
sneakers:{
id: 2,
title: 'Sneakers',
routeName: 'sneakers',
items: [
{
id: 10,
name: 'Adidas NMD',
imageUrl: 'https://i.ibb.co/0s3pdnc/adidas-nmd.png',
price: 220
},
{
id: 11,
name: 'Adidas Yeezy',
imageUrl: 'https://i.ibb.co/dJbG1cT/yeezy.png',
price: 280
},
{
id: 12,
name: 'Black Converse',
imageUrl: 'https://i.ibb.co/bPmVXyP/black-converse.png',
price: 110
},
{
id: 13,
name: 'Nike White AirForce',
imageUrl: 'https://i.ibb.co/1RcFPk0/white-nike-high-tops.png',
price: 160
},
{
id: 14,
name: 'Nike Red High Tops',
imageUrl: 'https://i.ibb.co/QcvzydB/nikes-red.png',
price: 160
},
{
id: 15,
name: 'Nike Brown High Tops',
imageUrl: 'https://i.ibb.co/fMTV342/nike-brown.png',
price: 160
},
{
id: 16,
name: 'Air Jordan Limited',
imageUrl: 'https://i.ibb.co/w4k6Ws9/nike-funky.png',
price: 190
},
{
id: 17,
name: 'Timberlands',
imageUrl: 'https://i.ibb.co/Mhh6wBg/timberlands.png',
price: 200
}
]
},
jackets:{
id: 3,
title: 'Jackets',
routeName: 'jackets',
items: [
{
id: 18,
name: 'Black Jean Shearling',
imageUrl: 'https://i.ibb.co/XzcwL5s/black-shearling.png',
price: 125
},
{
id: 19,
name: 'Blue Jean Jacket',
imageUrl: 'https://i.ibb.co/mJS6vz0/blue-jean-jacket.png',
price: 90
},
{
id: 20,
name: 'Grey Jean Jacket',
imageUrl: 'https://i.ibb.co/N71k1ML/grey-jean-jacket.png',
price: 90
},
{
id: 21,
name: 'Brown Shearling',
imageUrl: 'https://i.ibb.co/s96FpdP/brown-shearling.png',
price: 165
},
{
id: 22,
name: 'Tan Trench',
imageUrl: 'https://i.ibb.co/M6hHc3F/brown-trench.png',
price: 185
}
]
},
womens:{
id: 4,
title: 'Womens',
routeName: 'womens',
items: [
{
id: 23,
name: 'Blue Tanktop',
imageUrl: 'https://i.ibb.co/7CQVJNm/blue-tank.png',
price: 25
},
{
id: 24,
name: 'Floral Blouse',
imageUrl: 'https://i.ibb.co/4W2DGKm/floral-blouse.png',
price: 20
},
{
id: 25,
name: 'Floral Dress',
imageUrl: 'https://i.ibb.co/KV18Ysr/floral-skirt.png',
price: 80
},
{
id: 26,
name: 'Red Dots Dress',
imageUrl: 'https://i.ibb.co/N3BN1bh/red-polka-dot-dress.png',
price: 80
},
{
id: 27,
name: 'Striped Sweater',
imageUrl: 'https://i.ibb.co/KmSkMbH/striped-sweater.png',
price: 45
},
{
id: 28,
name: 'Yellow Track Suit',
imageUrl: 'https://i.ibb.co/v1cvwNf/yellow-track-suit.png',
price: 135
},
{
id: 29,
name: 'White Blouse',
imageUrl: 'https://i.ibb.co/qBcrsJg/white-vest.png',
price: 20
}
]
},
mens:{
id: 5,
title: 'Mens',
routeName: 'mens',
items: [
{
id: 30,
name: 'Camo Down Vest',
imageUrl: 'https://i.ibb.co/xJS0T3Y/camo-vest.png',
price: 325
},
{
id: 31,
name: 'Floral T-shirt',
imageUrl: 'https://i.ibb.co/qMQ75QZ/floral-shirt.png',
price: 20
},
{
id: 32,
name: 'Black & White Longsleeve',
imageUrl: 'https://i.ibb.co/55z32tw/long-sleeve.png',
price: 25
},
{
id: 33,
name: 'Pink T-shirt',
imageUrl: 'https://i.ibb.co/RvwnBL8/pink-shirt.png',
price: 25
},
{
id: 34,
name: 'Jean Long Sleeve',
imageUrl: 'https://i.ibb.co/VpW4x5t/roll-up-jean-shirt.png',
price: 40
},
{
id: 35,
name: 'Burgundy T-shirt',
imageUrl: 'https://i.ibb.co/mh3VM1f/polka-dot-shirt.png',
price: 25
}
]
}
};
export default SHOP_DATA;
Please provide any pointers or advice on what am I doing wrong? I keep getting the error. It seems that the collection is undefined. I don't understand why. Ideally it should return an object.
You are exporting the component like this
const mapStateToProps = (state,ownProps) => ({
collections: selectCollectionItem(ownProps.match.params.collectionId)(state)
})
export default connect(mapStateToProps)(CollectionPage);
The ownProps.match.params.collectionId might be undefined.
Add this at the top of your file
import { withRouter} from 'react-router-dom'
and export your component like
export default connect(mapStateToProps)(withRouter(CollectionPage));

How to manipulate the object inside the array using javascript?

var arr = [
{ id: 1, name: 'Ahmed Malick', school: 'TEWGS' },
{ id: 2, name: 'Tehmeed Anwar', school: 'DGS' },
{ id: 3, name: 'Azhar Yameen', school: 'DGS' }
]
I want this output:
The student name is his id is and he studies in
Can you please show me what kind of output you expect. Then i will try to solve it.
I'm not sure if this is what you want
var arr = [
{ id: 1, name: "Ahmed Malick", school: "TEWGS" },
{ id: 2, name: "Tehmeed Anwar", school: "DGS" },
{ id: 3, name: "Azhar Yameen", school: "DGS" },
];
arr.map((student) => {
return `Name: ${student.name}, id: ${student.id}, he studies in: ${student.school}`;
}).forEach((output) => {
console.log(output);
});
If you want it in the DOM do this
let html = arr.map((student) => {
return `<p><strong>Name</strong>: ${student.name}, <strong>id</strong>: ${student.id},<strong> he studies in</strong> ${student.school}</p>`;
}).join("")
document.createElement("div").innerHTML = html
Try thatGood luck

How to check if arrays have the same object React Native [duplicate]

This question already has answers here:
An efficient way to get the difference between two arrays of objects?
(4 answers)
Closed 3 years ago.
I have two arrays:
const array1 = [
{ id: 1, name: 'John', score: 124 },
{ id: 2, name: 'Angie', score: 80 },
{ id: 3, name: 'Max', score: 56 }
]
const array2 = [
{ id: 5, name: 'Lisa', score: 78 },
{ id: 2, name: 'Angie', score: 80 }
]
JSON.stringify(array1) == JSON.stringify(array2) is not a solution, because arrays have different number of objects.
array1.some(item=> array2.includes(item)) doesnt't work too.
If there a solution?
What i would suggest is since your id is unique , so try the below :
const array1 = [
{ id: 1, name: 'John', score: 124 },
{ id: 2, name: 'Angie', score: 80 },
{ id: 3, name: 'Max', score: 56 }
]
const array2 = [
{ id: 5, name: 'Lisa', score: 78 },
{ id: 2, name: 'Angie', score: 80 }
]
var array2Id = {}
array2.forEach(function(obj){
bIds[obj.id] = obj;
});
// Return all elements in A, unless in B
let check = array1.filter(function(obj){
return !(obj.id in array2Id);
});
console.log(check,'there')
if check is an empty array that means both are same otherwise it will give the different objects.
Hope it helps feel free for doubts
Here is a quick solution, maybe not the most performant.
const array1 = [
{ id: 1, name: 'John', score: 124 },
{ id: 2, name: 'Angie', score: 80 },
{ id: 3, name: 'Max', score: 56 },
];
const array2 = [
{ id: 5, name: 'Lisa', score: 78 },
{ id: 2, name: 'Angie', score: 80 },
];
// Index will have -1 if there is no match, otherwise it'll have
// the index of the first found match in array1.
const index = array1.findIndex(array1Item => {
// This will return the index if found, otherwise -1
const match = array2.findIndex(array2Item => {
// return array1Item.id === array2Item.id;
return JSON.stringify(array1Item) === JSON.stringify(array2Item);
});
return match > -1;
});
Instead of stringifying the entire object, if id is unique, you can just compare id as shown in the commented code.
Be advised this could have a complexity of O(n^2) where n is your array sizes. Big arrays may take a while.
Here is it running on PlayCode. It logs index as 1 because the first match is the second item in array1.

How to get total of numbers in an array from SharePoint list items

I'm creating a spfx web part using Reactjs. I have a function getting an array of items from a SharePoint list that includes a number column of "Hours". I need to get a total for all the hours that have been returned but can't figure out how to calculate that.
I feel like I'm missing something simple but I've run through all kinds of loops and for some reason I can't get it to work. I've verified that I am getting data from the Hours column.
I'll also state the obligatory "I'm new to spfx and react". :) TIA for any help!
private readItem(): void {
this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('Time Off')/items?$select=Title,Id,Hours`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept': 'application/json;odata=nometadata',
'odata-version': ''
}
}).then((response: SPHttpClientResponse): Promise<ITimeOffItem[]> => {
return response.json();
})
.then((item: ITimeOffItem[]): void => {
console.log(item); //the data is here including Hours
this.setState({
items: item,
hoursTotal: //????How do I get the sum of "Hours" and assign it to a number in state
});
});
}
Create a function to loop through the items and add the hours
function countHours(items) {
if (!items) {
return 0;
}
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].Hours;
}
return total;
}
const item = [
{ Id: 25, Title: "Comp Time", Hours: 6, ID: 25 },
{ Id: 26, Title: "Comp Time", Hours: 5, ID: 26 },
{ Id: 27, Title: "Work from Home", Hours: 3, ID: 27 },
{ Id: 28, Title: "Comp Time", Hours: 7, ID: 28 },
{ Id: 29, Title: "Work from Home", Hours: 8, ID: 29 },
{ Id: 30, Title: "Holiday", Hours: 8, ID: 30 },
{ Id: 31, Title: "Work from Home", Hours: 32, ID: 31 }
];
console.log(countHours(item));
Use it like
this.setState({
items: item,
hoursTotal: countHours(item)
});
you can also use reduce
const item = [
{ Id: 25, Title: "Comp Time", Hours: 6, ID: 25 },
{ Id: 26, Title: "Comp Time", Hours: 5, ID: 26 },
{ Id: 27, Title: "Work from Home", Hours: 3, ID: 27 },
{ Id: 28, Title: "Comp Time", Hours: 7, ID: 28 },
{ Id: 29, Title: "Work from Home", Hours: 8, ID: 29 },
{ Id: 30, Title: "Holiday", Hours: 8, ID: 30 },
{ Id: 31, Title: "Work from Home", Hours: 32, ID: 31 }
];
const sum = item.reduce(function(a, b) { return a + b.Hours; }, 0);
console.log(sum)
It's hard to answer this without knowing what the data structure looks like, but if you are trying to sum an array of numbers you could use reduce.
const hours = [7, 5, 3, 1, 7]
const totalHours = hours.reduce((accumulator, hour) => accumulator + hour)

Resources