Динамически получать значения объекта из массива - PullRequest
0 голосов
/ 11 апреля 2019

Допустим, у меня есть Объект myBook и массив allCategories.

const allCategories = ["sciencefiction", "manga", "school", "art"];

const myBook = {
   isItScienceFiction: true,
   isItManga: false,
   isItForKids: false
}

Что я хочу: Перебирать категории, чтобы проверить значение Book, напримерпроверьте, существует ли "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>
    );
});

Если вам нужна дополнительная информация, просто дайте мне знать, яотредактирую мой вопрос.

Ответы [ 8 ]

3 голосов
/ 11 апреля 2019

Вы можете использовать методы 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.log(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.log(result)
1 голос
/ 11 апреля 2019

Преобразование 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.log(
    allCategories.filter(category => !!newMyBook[category]).map(category => `<p>${category}</p>`)
);
1 голос
/ 11 апреля 2019

Вы можете изменить имена ключей в 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.log(haveCategories)
1 голос
/ 11 апреля 2019

Вы можете попробовать вот так:

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);
1 голос
/ 11 апреля 2019

Используйте Array.filter() и Array.find() с RegExp, чтобы найти категории с соответствующими ключами.Используйте Array.map() для преобразования категорий в строки / 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);
1 голос
/ 11 апреля 2019

Вы можете создать 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.log(key, keyInObject, value)

  if(keyInObject && value) {
    // do something if has the current key and the value is true
  }
})
1 голос
/ 11 апреля 2019

Вы действительно не должны хранить ряд свойств, содержащих логические значения.Хотя это может работать для 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>)
1 голос
/ 11 апреля 2019

Вы можете использовать

Object.keys(myBook).forEach(function(key){console.log(myBook[key])})

... вместо кода console.log.Это может сделать трюк без жесткого кодирования, а также с лучшей практикой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...