Начинаем сначала

Ну вот мы вроде с 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/