Допустим, у меня есть объект myBook
и массив allCategories
.
const allCategories = ["sciencefiction", "manga", "school", "art"];
const myBook = {
isItScienceFiction: true,
isItManga: false,
isItForKids: false
}
Что я хочу : Перебрать категории, чтобы проверить значение книги, например, проверить, существует ли "sciencefiction"
в моем объекте книги, а затем проверить его значение
Что я пробовал:
1) С indexOf
allCategories.map((category) => {
Object.keys(myBook).indexOf(category)
// Always returns -1 because "sciencefiction" doesn't match with "isItScienceFiction"
});
2) С includes
allCategories.map((category) => {
Object.keys(myBook).includes(category)
// Always returns false because "sciencefiction" doesn't match with "isItScienceFiction"
});
Ожидаемый результат:
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>
);
});
Если вам нужна дополнительная информация, просто дайте мне знать, я отредактирую свой вопрос.
🤔 А знаете ли вы, что...
JavaScript имеет множество библиотек и фреймворков, таких как jQuery, Angular, и Vue.js.
Вы можете использовать методы filter
и find
для возврата нового массива категорий, а затем использовать метод map
для возврата массива элементов.
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.info(result)
Вы также можете использовать reduce
вместо filter
и map
и endsWith
метода.
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.info(result)
Вы можете использовать
Object.keys(myBook).forEach(function(key){console.info(myBook[key])})
... поместите свой код вместо console.info
. Это может помочь без жесткого кодирования, а также является передовой практикой.
Вы действительно не должны хранить ряд свойств, содержащих логические значения. Хотя это может сработать для 1, 2 или 3 категорий, для нескольких сотен это не сработает. Вместо этого просто сохраните категории в массиве:
const myBook = {
categories: ["sciencefiction", "manga", "kids"],
};
Если у вас уже есть объект со старой структурой, вы можете легко преобразовать его:
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 };
};
Теперь, чтобы проверить, содержит ли книга определенную категорию:
const isManga = myBook.categories.includes("manga");
И ваш рендеринг теперь также довольно прост:
myBook.categories.map(it => <p>{it}</p>)
Вы можете создать Map
для категорий и ключей объекта:
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.info(key, keyInObject, value)
if (keyInObject && value) {
// do something if has the current key and the value is true
}
})
Используйте Array.filter()
и Array.find()
с регулярным выражением, чтобы найти категории с совпадающими ключами. Используйте Array.map()
для преобразования категорий в строки/JSX/и т.д....
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.info(result);
Вы можете попробовать так:
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.info(result);
Вы можете изменить имена ключей в объекте myBook
для удобства поиска, например:
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.info(haveCategories)
Преобразование sciencefiction
в isItScienceFiction
невозможно, а зацикливание всех ключей myBook
для каждого category
не оптимально.
Но преобразовать isItScienceFiction
в sciencefiction
довольно просто, поэтому вы можете создать newMyBook
из своего myBook
и использовать его для проверки.
Создание newMyBook
— это одноразовые накладные расходы.
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.info(
allCategories.filter(category => !!newMyBook[category]).map(category => `<p>${category}</p>`)
);