Начинаем сначала
Ну вот мы вроде с forEach
более-менее разобрались. Теперь пойдем мучать map
Начнем с нуля. То есть пусть у нас опять просто index.html
вида:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<body>
<h1>Hello, world!</h1>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<script src="/main.js"></script>
</body>
</html>
и файлик main.js
вида
// main.js
async function process() {
let r = await fetch("/data.json");
let data = await r.json();
}
process()
еще у меня есть файлик с данными data.json
в нем список словариков вида
{
"ID": "1385327090",
"Отметь, в какой мере ты удовлетворен курсом?": "В основном",
"Насколько курс был интересен?": "Интересный",
"Насколько курс был полезен?": "Полезный",
"Насколько материал курса был понятен?": "В основном",
"Насколько доволен форматом обучения?": "В основном",
"Оцени работу преподавателя по шкале от 1-10 / 10 – высоко оцениваю работу преподавателя. 1 – совсем не понравилась работа преподавателя": "8"
},
я хочу из этого списка получить, например, набор всевозможных ответов по ключу Насколько курс был полезен?

и тут нам приходит на помощь функция map
Функция map
map
– переводится как отображение
, либо как карта, что в принципе есть упрощённое отображение реальной местности на картинку. Помнишь там всякие масштабы, география, все дела…
В общем с помощью этой функции я хочу упростить исходный список словариков и превратить его в список фраз.
Попробуем сначала воспользоваться функций map, которая ничего не меняет.
Пишем
async function process() {
let r = await fetch("/data.json");
let data = await r.json();
console.log(data) // выведем исходный список
let mappedData = data.map(item => {
return item;
}) // мэпю
console.log(mappedData) // выведем отображенный список
}
process()
глянем что получится в консоли:

можно заметить, что он вывел два одинаковых списка словариков.
Давай теперь разберемся что за магия в строчках
let mappedData = data.map(item => {
return item;
})
Если помнишь с прошлого задания то =>
означает объявление анонимной функции, то что слева от стрелочки – это параметр функции, а то что справа – это то что делает функция.
map
работает по тому же принципу что и forEach
, то есть он берет каждый элемент списка data, передает его в аргумент функции, а функция делает что?
Делает return item
. То есть возвращает значение.
И этот же map собирает эти возвращенные значения обратно, но уже в новый список.
Если пока не понятно. То вот тебе более простой пример
let mappedData = [1,2,3,4].map(item => {
return item
})
что это выдаст? Очевидно [1,2,3,4]

Ну мэп не был бы мэпом, если бы он не давал бы возможность изменить значение.
Мы можем, например, взять и умножить все значения исходного массива на 2, вот так:
let mappedData = [1,2,3,4].map(item => {
return item * 2
})

а можем даже фразу слепить
let mappedData = [1,2,3,4].map(item => {
return `${item} + ${item} = ${item * 2}`
})


Ленивые программисты
так как программисты не любя писать лишний код, то они вот эти штуки любят писать в упрощённом виде.
вместо
let mappedData = [1,2,3,4].map(item => {
return `${item} + ${item} = ${item * 2}`
})
они пишут
let mappedData = [1,2,3,4].map(item => `${item} + ${item} = ${item * 2}`)
вместо
let mappedData = [1,2,3,4].map(item => {
return item * 2
})
пишут
let mappedData = [1,2,3,4].map(item => item * 2)
а вместо
let mappedData = data.map(item => {
return item;
})
пишут
let mappedData = data.map(item => item)
грубо говоря если анонимная функция просто возвращает значение, то ее можно записать в упрощённом виде, без всяких этих ваших return
let mappedData = data.map(item => возвращаемое_значение)
Вырезаем значения по ключу
Вернемся к нашему списку
[
...
{
"ID": "1385327090",
"Отметь, в какой мере ты удовлетворен курсом?": "В основном",
"Насколько курс был интересен?": "Интересный",
"Насколько курс был полезен?": "Полезный",
"Насколько материал курса был понятен?": "В основном",
"Насколько доволен форматом обучения?": "В основном",
"Оцени работу преподавателя по шкале от 1-10 / 10 – высоко оцениваю работу преподавателя. 1 – совсем не понравилась работа преподавателя": "8"
},
...
]
Как я уже говорил, я хочу из этого списка получить например набор всевозможных ответов по ключу Насколько курс был полезен?
Таким образом наш код
async function process() {
let r = await fetch("/data.json");
let data = await r.json();
console.log(data) // выведем исходный список
let mappedData = data.map(item => {
return item;
}) // мэпю
console.log(mappedData) // выведем отображенный список
}
process()
можно написать следующим образом
async function process() {
let r = await fetch("/data.json");
let data = await r.json();
console.log(data)
let mappedData = data.map(item => {
return item['Насколько курс был полезен?']; // добавил конкретный ключ
})
console.log(mappedData)
}
process()
глянем что выведется

ого, мы получили 38
значений, и там только значения ключа Насколько курс был полезен?
То, что нам и надо =О
Теперь бы только уникальные получить…
Оставляем только уникальные значения
Если у тебя есть список не уникальных значений, то ты можешь сделать из него список только уникальных значений, если воспользуешься небольшим хаком.
В js есть специальный объект которые называется Set
.
Set – переводится как множество. Согласно формальной математике, множество не имеет повторяющихся значений.
Поэтому, если ты хочешь из списка оставить только набор уникальных значений, то надо преобразовать список в множество.
Делается это так:
let uniqueValues = new Set(mappedData)
console.log(uniqueValues)

но так как Set это не совсем список, у него, например, нет метода map
или forEach
, то надо немного схитрить, и множество обратно переделать в список, вот так:
let uniqueValues = [...new Set(mappedData)] // это такой хитрый способ перегнать множество в список
console.log(uniqueValues)

Создаем выпадающий список
На кой мне эти уникальный значения? – спросишь ты.
Я хочу сделать выпадающий список, который будет содержать список возможных значений по конкретному ключу. И будем потом по ним фильтровать
О как я придумал. Но это потом =О
И так, задача:
Дано: список уникальных значений
Надо: вывести select на форму
идем верстать

Я буду банален, загоню вот такое:
<div class="container mt-2">
<div class="row">
<div class="col">
<select class="form-select" id="selectPoleznost"></select>
</div>
</div>
</div>

теперь я хочу загнать в этот select
список возможных значений.
Идем в main.js
.
Сначала найдем выпадающий список на форме
let select = document.querySelector("#selectPoleznost");
console.log(select)

кстати если мышкой наводить в консольке, то должен подсвечивать на форме:

теперь заполню список. Для этого нам пригодится уже знакомый нам метод forEach
uniqueValues.forEach(item => {
console.log(item)
})

так как мы хотим не выводить в консоль значение из списка uniqueValues
, а создавать по ним элементы, то нам надо в тело анонимной функции загнать:
uniqueValues.forEach(item => {
// создаем в памяти элемент выпадающего списка
let option = document.createElement("option");
option.value = item; // устанавливаем значение элемента
option.text = item; // устанавливаем текст элемента, он совпадает со значением
select.add(option) // добавляем элемент к выпадающему списку
})

можно потестить:

красота =)
Го пилить задание)
Задание
Добавить выпадающие списки с уникальными значениями для ключей
Отметь, в какой мере ты удовлетворен курсом?
Насколько доволен форматом обучения?
и сверстать чтобы они вверху в ряд стояли, как-то так:

Как располагать элементы формы можно подсмотреть тут https://getbootstrap.com/docs/5.3/forms/layout/