Let's say I have an Object myBook
and an array allCategories
.
const allCategories = ["sciencefiction", "manga", "school", "art"];
const myBook = {
isItScienceFiction: true,
isItManga: false,
isItForKids: false
}
What I want : Loop over categories to check the value of Book, for example, check if "sciencefiction"
exists in my Book Object and then check it's value
What I have tried :
1) With indexOf
allCategories.map((category) => {
Object.keys(myBook).indexOf(category)
// Always returns -1 because "sciencefiction" doesn't match with "isItScienceFiction"
});
2) With includes
allCategories.map((category) => {
Object.keys(myBook).includes(category)
// Always returns false because "sciencefiction" doesn't match with "isItScienceFiction"
});
Expected output :
allCategories.map((category) => {
// Example 1 : Returns "sciencefiction" because "isItScienceFiction: true"
// Example 2 : Returns nothing because "isItManga: false"
// Example 3 : Returns nothing because there is not property in myBook with the word "school"
// Example 4 : Returns nothing because there is not property in myBook with the word "art"
// If category match with myBook categories and the value is true then
return (
<p>{category}</p>
);
});
If you need more information, just let me know, I'll edit my question.
You could use filter
and find
methods to return new array of categories and then use map
method to return array of elements.
const allCategories = ["sciencefiction", "manga", "school", "art"]; const myBook = {isItScienceFiction: true, isItManga: false, isItForKids: false} const result = allCategories.filter(cat => { const key = Object.keys(myBook).find(k => k.slice(4).toLowerCase() === cat); return myBook[key] }).map(cat => `<p>${cat}</p>`) console.log(result)
You can also use reduce
instead of filter
and map
and endsWith
method.
const allCategories = ["sciencefiction", "manga", "school", "art"]; const myBook = {isItScienceFiction: true,isItManga: false,isItForKids: false} const result = allCategories.reduce((r, cat) => { const key = Object.keys(myBook).find(k => k.toLowerCase().endsWith(cat)); if(myBook[key]) r.push(`<p>${cat}</p>`) return r; }, []) console.log(result)
You can use
Object.keys(myBook).forEach(function(key){console.log(myBook[key])})
... place you code instead of console.log
. This can do the trick without hard coding and also the best practice.
You should really not keep a number of properties containing booleans. While that might work for 1, 2 or 3 categories, for a few hundred it won't work well. Instead, just store the categories in an array:
const myBook = {
categories: ["sciencefiction", "manga", "kids"],
};
If you got some object with the old structure already, you can easily convert them:
const format = old => {
const categories = [];
if(old.isItScienceFiction)
categories.push("sciencefiction");
if(old.isItManga)
categories.push("manga");
if(old.isItForKids)
categories.push("kids");
return { categories };
};
Now to check wether a book contains a certain category:
const isManga = myBook.categories.includes("manga");
And your rendering is also quite easy now:
myBook.categories.map(it => <p>{it}</p>)
You could create a Map
for the the categories and keys of object:
const allCategories = ["sciencefiction", "manga", "school", "art"], myBook = { isItScienceFiction:true, isItManga:false, isItForKids:false } const map = Object.keys(myBook) .reduce((r, k) => r.set(k.slice(4).toLowerCase(), k), new Map); /* map: {"sciencefiction" => "isItScienceFiction"} {"manga" => "isItManga"} {"forkids" => "isItForKids"} */ allCategories.forEach(key => { let keyInObject = map.get(key); // the key name in object let value = myBook[keyInObject]; // value for the key in object console.log(key, keyInObject, value) if(keyInObject && value) { // do something if has the current key and the value is true } })
Use Array.filter()
and Array.find()
with a RegExp to find categories that have matching keys. Use Array.map()
to convert the categories to strings/JSX/etc...
const findMatchingCategories = (obj, categories) => { const keys = Object.keys(obj); return allCategories .filter(category => { const pattern = new RegExp(category, 'i'); return obj[keys.find(c => pattern.test(c))]; }) .map(category => `<p>${category}</p>`); }; const allCategories = ["sciencefiction", "manga", "school", "art"]; const myBook = { isItScienceFiction: true, isItManga: false, isItForKids: false }; const result = findMatchingCategories(myBook, allCategories); console.log(result);
You can try like this:
const allCategories = ["sciencefiction", "manga", "school", "art"]; const myBook = { isItScienceFiction: true, isItManga: false, isItForKids: false }; const myBookKeys = Object.keys(myBook); const result = allCategories.map(category => { const foundIndex = myBookKeys.findIndex(y => y.toLowerCase().includes(category.toLowerCase())); if (foundIndex > -1 && myBook[myBookKeys[foundIndex]]) return `<p>${category}</p>`; }); console.log(result);
You can modify the key names in myBook
object for easy lookup like:
const allCategories = ["sciencefiction", "manga", "school", "art"];
const myBook = {
isItScienceFiction: true,
isItManga: false,
isItForKids: false
}
const modBook = {}
Object.keys(myBook).map((key) => {
const modKey = key.slice(4).toLowerCase()
modBook[modKey] = myBook[key]
})
const haveCategories = allCategories.map((category) => {
if (modBook[category]) {
return <p>{category}</p>
}
return null
})
console.log(haveCategories)
Converting sciencefiction
to isItScienceFiction
is not possible and looping all the keys of myBook
for every category
is not optimal.
But converting isItScienceFiction
to sciencefiction
is pretty easy, so you can create newMyBook
from your myBook
and use it instead to check.
Creating newMyBook
is a one time overhead.
const allCategories = ["sciencefiction", "manga", "school", "art"]; const myBook = {isItScienceFiction: true,isItManga: false,isItForKids: false}; const newMyBook = Object.keys(myBook).reduce((a, k) => { return { ...a, [k.replace('isIt', '').toLowerCase()]: myBook[k] }; }, {}); console.log( allCategories.filter(category => !!newMyBook[category]).map(category => `<p>${category}</p>`) );
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.