Проблемный вопрос по кодированию, касающийся JavaScript

Я прохожу курс кодирования в Codecademy и в настоящее время застрял в определенном вопросе в рамках задачи по кодированию. Я получил 3 JS-файла, два из которых мне не следует каким-либо образом изменять, так как мне сказали, что это вспомогательные функции, которые мне следует использовать, и файл с массивом книг. Вопрос 2 полностью сбивает меня с толку. Я сидел над ним уже целых 2 часа, и хотя он работает локально на vscode, он снова и снова выдает мне одно и то же сообщение об ошибке. Буду очень признателен за любую помощь, потому что я очень расстроен. Сначала я пришлю описание задачи и первый вопрос для дополнительного контента:

Вступление: В редакторе кода мы предоставили вам стартовый код веб-сайта Book Finder. Как только заявка будет заполнена, вы сможете ввести жанр, название или автора в строку поиска и получить список книг, соответствующих этим критериям. Вы можете увидеть список книг, которые ваше приложение будет искать в bookList.js.

Ваша задача — завершить сборку приложения, заполнив определения функций captureSearchValue(), filterBooks(), StructureBooksAsHtml() и searchBtnClickHandler(). Вам следует вносить изменения только в эти четыре определения функций в script.js. В helper.js мы определили вспомогательные функции, которые вам нужно будет использовать при создании программы.

Вопрос 1: Функция captureSearchValue фиксирует входное значение панели поиска и возвращает его.

По их мнению, мой код для первого вопроса правильный.

Вопрос 2: Функция filterBooks() принимает строку поиска и список книг в качестве параметров и возвращает все книги, которые содержат точное соответствие входным данным поиска, в виде массива объектов. Объекты в этом массиве должны быть отформатированы как книги со свойствами названия, автора и тегов, аналогично исходному массиву книг. Он должен использовать функцию FlattenObjectValuesIntoArray() для легкого поиска по всем полям внутри объекта книги.

Вспомогательный код:

// Flatten object keys into an array so that we search the entire object by the input value
const flattenObjectValuesIntoArray = (arrOfObjs) => {
  let flattenedObj;
  const flattenedObjsArr = [];
  for (let obj = 0; obj < arrOfObjs.length; obj++) {
    const objValues = Object.values(arrOfObjs[obj]);
    flattenedObj = [...objValues.flat()]
    flattenedObjsArr.push(flattenedObj)
  }
  return flattenedObjsArr;
};

// Structure filtered books as HTML and return
const structureBookAsHtml = (book) => {
  const bookDiv = document.createElement("div");
  bookDiv.setAttribute('class', 'bookDiv');
  
  const bookTitle = document.createElement("h2");
  bookTitle.innerHTML = book.title;
  bookTitle.setAttribute('class', 'bookTitle');

  const bookAuthor = document.createElement("h3");
  bookAuthor.innerHTML = book.author;

  const bookTags = document.createElement("p");
  bookTags.innerHTML = book.tags.join(", ");

  bookDiv.append(bookTitle, bookAuthor, bookTags);
  
  return bookDiv;
};

const renderBooksToDom = (elements) => {
  const bookListContainer = document.querySelector("#bookList");
  bookListContainer.innerHTML = "";

  bookListContainer.append(...elements);
};

Файл массива:

const books = [
  {
    title: "The City We Became",
    author: "N. K. Jemisin",
    tags: ["fantasy", "fiction", "afrofutursim", "science fiction", "sci-fi"]
  },
  {
    title: "The Catcher in the Rye",
    author: "J. D. Salinger",
    tags: ["fiction", "young adult", "YA", "realism", "coming of age", "classic"]
  },
  {
    title: "The Hundred Thousand Kingdoms",
    author: "N. K. Jemisin",
    tags: ["fantasy", "fiction", "adventure", "series"]
  },
  {
    title: "Sapiens: A Brief History of Humankind",
    author: "Yuval Noah Harari",
    tags: ["nonfiction", "history", "anthropology", "science", "sociology"]
  },
  {
    title: "Behave: The Biology of Humans at Our Best and Worst",
    author: "Robert M. Sapolsky",
    tags: ["nonfiction", "anthropology", "science", "sociology", "biology"]
  },
  {
    title: "The Parable of the Talents",
    author: "Octavia Butler", 
    tags: ["fiction", "dystopian", "science fiction"]
  },
  {
    title: "1984",
    author: "George Orwell", 
    tags: ["fiction", "dystopian", "science fiction", "classics", "adult"]
  },
  {
    title: "Remarkably Bright Creatures",
    author: "Shelby Van Pelt",
    tags: ["fiction", "mystery", "magical realism"]
  },
  {
    title: "Crying in H Mart",
    author: "Michelle Zauner",
    tags: ["memoir", "nonfiction", "autobiography"]
  },
  {
    title: "Wild: From Lost to Found on the Pacific Crest Trail",
    author: "Cheryl Strayed",
    tags: ["nonfiction", "memoir", "adventure", "travel"]
  }
]

Индекс.html:

<!DOCTYPE html>
<html>
  <head>
    <link rel = "stylesheet" href = "styles.css">
    <script src = "bookList.js"></script>
    <script src = "bookList.test.js"></script>
    <script src = "helper.js"></script>
    <script src = "script.js" defer></script>
  </head>
  <body>
    <h1>Book Finder</h1>
    <input id = "search-bar" type = "text" placeholder = "Search for books by tags">
    <button class = "btn" id = "search-btn">Search</button>
    <div id = "bookList">
      <!-- List of books will be rendered here -->
    </div>
  </body>
</html>

мой код:

// Click handler for search button
let cap = document.getElementById('search-bar')
let capValue = cap.value;
const captureSearchValue = () => {
return cap.value
};

const filterBooks = () => {
  let flattenedArr =flattenObjectValuesIntoArray(books);
  let match = [];
  for (let i = 0; i < flattenedArr.length; i++) {
    for (let j = 0; j < flattenedArr[i].length; j++) {
      if (flattenedArr[i][j] === capValue){
        match.push(books[i])
      }
    }
  }; return match
  };

// Empty the book list container, iterate over list of filtered books, return list of books formatted as HTML using the function in `helper.js`
const structureBooksAsHtml = () => {};

// Handler triggered when a user clickers the "Search" button. Chains previously defined functions together to filter books based on the search value, formats the books as HTML and renders them to the DOM
const searchBtnClickHandler = () => {};

// Grab search button from the DOM

// Attach an event listener to the search button
searchBtn.addEventListener("click", () => {
  searchBtnClickHandler(books);
});

Я занимаюсь только функцией filterBooks, до других функций я еще не добрался, так что не обращайте на них внимания.

Это сообщение, которое я получаю на вопрос 2, когда отправляю свой ответ:

Учитывая фильтр fantasy, ваша функция filterBooks вернула массив с элементами 0. Мы ожидали его возвращения 2.

Буду очень признателен за любую помощь по этой проблеме. Мне кажется, это не имеет никакого смысла

Я думаю, что проблема связана с капитализацией, но я, честно говоря, понятия не имею.

«Функция filterBooks() принимает в качестве параметров строку поиска и список книг». Ваша функция filerBooks должна иметь два параметра, в настоящее время у нее их нет. Итак, capValue и books должны быть параметрами. Вам не нужно создавать capaValue в глобальной области (т. е. выше captureSearchValue).

Nick Parsons 14.04.2024 13:04
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
269
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы создали переменную вне функции, которая задается при загрузке DOM один раз, поэтому при загрузке DOM входное значение search-bar равно ''. Вот почему при выполнении цикла вы каждый раз проверяете, равна ли строка book значению ''. Это вызывает проблему.

Есть простое решение этой проблемы: просто используйте функцию captureSearchValue, чтобы создать переменную capValue внутри функции fiterBooks, и тогда она будет работать нормально.

Вот как должен выглядеть ваш код

const searchBtn = document.querySelector('#search-btn');

// Click handler for search button
let cap = document.getElementById('search-bar')
// Remove the capValue variable
const captureSearchValue = () => {
    return cap.value
};

const filterBooks = () => {
    let flattenedArr = flattenObjectValuesIntoArray(books);
    // Add the capValue variable here
    let capValue = captureSearchValue();
    let match = [];
    for (let i = 0; i < flattenedArr.length; i++) {
        for (let j = 0; j < flattenedArr[i].length; j++) {
            if (flattenedArr[i][j] === capValue) {
                match.push(books[i])
            }
        }
    };
    return match
};

Если это не сработает, вы также можете попробовать изменить условие на:

if (flattenedArr[i][j].includes(capValue)) {
    match.push(books[i])
}

Предыдущее условие проверяло, соответствует ли значение строки книги на 100% значению поиска, что также может вызывать проблему, например 'fantasy' !== ' fantasy ' даже пробел может привести к тому, что это значение будет ложным. Новое условие просто проверяет, включена ли строка или нет. Это также может решить проблему.

Привет! Я очень ценю помощь, но, к сожалению, после того, как я ее попробовал, я получил одно и то же сообщение: учитывая фильтр fantasy, ваша функция filterBooks вернула массив с элементами 0. Мы ожидали его возвращения 2. Я в таком замешательстве, что не вижу никакой причины, по которой это может быть неправильно...

Lenny Lorenz 15.04.2024 18:18

Я скопировал весь ваш код, просмотрел его, исправил проблему и обновил свой ответ. Проверьте еще раз, надеюсь, это решит проблему.

Abdur Rehman 16.04.2024 08:32

Вам действительно следует научиться:

  1. Фильтр работает, в данной ситуации это очень удобно.
  2. Карта работает, тоже удобно
  3. Найти работы, это то же самое, что и фильтр, но ограничивается 1 результатом.

Вы можете заменить все эти функции на forEach, но их изучение значительно улучшит ваш код :)

Это может быть результат:

///////////////////
// DATA
//////////////////
const books = [
  {
    title: "The City We Became",
    author: "N. K. Jemisin",
    tags: ["fantasy", "fiction", "afrofutursim", "science fiction", "sci-fi"]
  },
  {
    title: "The Catcher in the Rye",
    author: "J. D. Salinger",
    tags: ["fiction", "young adult", "YA", "realism", "coming of age", "classic"]
  },
  {
    title: "The Hundred Thousand Kingdoms",
    author: "N. K. Jemisin",
    tags: ["fantasy", "fiction", "adventure", "series"]
  },
  {
    title: "Sapiens: A Brief History of Humankind",
    author: "Yuval Noah Harari",
    tags: ["nonfiction", "history", "anthropology", "science", "sociology"]
  },
  {
    title: "Behave: The Biology of Humans at Our Best and Worst",
    author: "Robert M. Sapolsky",
    tags: ["nonfiction", "anthropology", "science", "sociology", "biology"]
  },
  {
    title: "The Parable of the Talents",
    author: "Octavia Butler", 
    tags: ["fiction", "dystopian", "science fiction"]
  },
  {
    title: "1984",
    author: "George Orwell", 
    tags: ["fiction", "dystopian", "science fiction", "classics", "adult"]
  },
  {
    title: "Remarkably Bright Creatures",
    author: "Shelby Van Pelt",
    tags: ["fiction", "mystery", "magical realism"]
  },
  {
    title: "Crying in H Mart",
    author: "Michelle Zauner",
    tags: ["memoir", "nonfiction", "autobiography"]
  },
  {
    title: "Wild: From Lost to Found on the Pacific Crest Trail",
    author: "Cheryl Strayed",
    tags: ["nonfiction", "memoir", "adventure", "travel"]
  }
]

///////////////////
// HELPERS
//////////////////
function flattenObjectValuesIntoArray (arrOfObjs) {
  let flattenedObj;
  const flattenedObjsArr = [];
  for (let obj = 0; obj < arrOfObjs.length; obj++) {
    const objValues = Object.values(arrOfObjs[obj]);
    flattenedObj = [...objValues.flat()]
    flattenedObjsArr.push(flattenedObj)
  }
  return flattenedObjsArr;
};

///////////////////
// TASK
//////////////////

/*
The filterBooks() function takes in a search string and a list of books as parameters and returns all of the books that contain an exact match of the search input as an array of objects.
*/

function filterBooks(search, books) {
  // Flatten books array
  flattenedBooks = flattenObjectValuesIntoArray(books);

  // Now we can filter for an EXACT match
  let results = flattenedBooks.filter(bookProps => 
    bookProps.filter((prop) => prop === search).length
 )
 
 // We still got to remap like the books array, but if we assume titles are unique, we can still use the original books array to find the correct objects.
 let mappedResults = results.map(book => books.find((b) => b.title === book[0]))
 
  
 return mappedResults
}


// EXAMPLE
console.info(filterBooks('fiction', books));

И последнее, но не менее важное: о

'fantasy' !== ' fantasy '

Это легко исправить с помощью функции Trim() :)

Другие вопросы по теме

Похожие вопросы

Есть ли способ получить данные об осадках в API OpenWeatherMap?
Ошибка создания токена для Token2022Form: TypeError: невозможно прочитать свойства неопределенного значения (чтение «вызова»)
Эффективный алгоритм частичного переупорядочения
Используйте один и тот же модуль для экспорта как в основной поток js, так и в веб-работник
Как я могу использовать ванильный JavaScript для настройки мобильной навигации, при которой щелчок по родительскому элементу навигации будет выполнять поиск дочернего элемента ul и добавлять класс?
Как добавить элемент к другому повернутому и позиционированному элементу, сохраняя его положение на экране?
Использование CreateBrowserRouter из React Router с хранилищем Redux
Получение моего Symfony API занимает почти 2 секунды
Как получить значение значения вложенного элемента ввода из моего собственного компонента реагирования в изолированном файле?
Node TS: знак токена JWT для проверки аутентификации между клиентом и серверной частью