Задачи по JavaScript для начинающих (6 задач + решение)
В этой статье мы рассмотрим 6 популярных задач по JavaScript для начинающих, которые частенько встречаются на собеседованиях на позицию Junior Frontend разработчика.
Решая задачи, мы будем тренироваться создавать переменные, а также использовать функции, массивы, циклы, объекты и многие другие базовые темы JavaScript.
Будет очень полезно, если перед просмотром решения каждой задачи вы попробуете ее решить самостоятельно.
Задача 1. Определить сколько раз каждый элемент встречается в массиве.
Имеется исходный массив:
1const fruits = ['kiwi', 'apple', 'kiwi', 'orange', 'kiwi', 'apple'];
Требуется получить ответ в следующем формате:
1// {kiwi: 3, apple: 2, orange: 1}
Чтобы решить задачу, давайте для начала создадим пустой объект, внутрь которого будем добавлять каждый элемент массива с нужным количеством.
1const count = {};
Далее мы можем использовать функцию forEach
, чтобы пробежаться по каждому элементу массива fruits
.
Для каждого элемента будем делать проверку - был ли он ранее добавлен в наш объект count
.
Если текущий элемент в объекте отсутсвует, то добавляем этот элемент со значением 1. В противном случае также добавляем элемент в объект, но его текущее значение увеличиваем на 1.
1const fruits = ['kiwi', 'apple', 'kiwi', 'orange', 'kiwi', 'apple'];23const count = {};45fruits.forEach(f => {67 if (!count[f]) {8 // Текущий элемент отсутствует в объекте count9 count[f] = 1;1011 } else {12 // Текущий элемент ранее был добавлен в объект count13 count[f] ++;14 }15});
Проверяем значение переменной count
:
1console.log(count);2// Object { kiwi: 3, apple: 2, orange: 1 }
Чтобы иметь возможность повторно использовать наше решение в разных частях приложения, давайте оформим его в виде функции.
1const countItems = (list) => {2 const count = {};34 list.forEach(f => {5 if (!count[f]) {6 count[f] = 1;7 } else {8 count[f] ++;9 }10 });1112 return count;13};
Таким образом, мы можем получать результат подсчета количества каждого элемента в любом массиве следующим образом:
1const countResult = countItems(fruits);23console.log(countResult);4// {kiwi: 3, apple: 2, orange: 1}
Задача 2. Создать массив который содержит только уникальные значения исходного массива.
Исходный массив:
1const fruits = ['kiwi', 'apple', 'kiwi', 'orange', 'kiwi', 'apple'];
Давайте рассмотрив 2 возможных решения этой задачи.
Задача 2. Вариант 1. Используем конструктор Set.
Самый простой способ создать массив с уникальными значениями - использовать конструктор Set
.
Данная функция-конструктор позволяет создавать объекты Set, которые хранят уникальные значения.
Значения могут относиться к любому типу.
1const fruitsUnique = new Set(fruits);2// Set(3) [ "kiwi", "apple", "orange" ]
На выходе мы получили так называемый Set
(коллекция) из 3-х уникальных значений.
Чтобы получить массив мы можем обернуть наш результат в метод Array.from()
.
1const fruitsUnique = Array.from(new Set(fruits));2// Array(3) [ "kiwi", "apple", "orange" ]
Задача 2. Вариант 2. Используем пустой объект и цикл forEach.
На одном из собеседований меня попросили создать массив из уникальных значений, без использования конструктора Set
.
Один из вариантов, как это можно сделать - использовать метод forEach
и последовательно добавлять
каждый элемент массива в пустой объект с произвольным значением (например true
):
1const myFruits = ['kiwi', 'apple', 'kiwi', 'orange', 'kiwi', 'apple'];23 const unique = {};45 myFruits.forEach(item => {6 unique[item] = true;7 });
Каждый, повторно встречающийся, элемент перезаписывается внутри объекта unique
последним значением.
Таким образом, наш объект unique
содержит только уникальные названия ключей.
1console.log(unique);2// Object { kiwi: true, apple: true, orange: true }
Чтобы получить массив из ключей объекта можно использовать метод Object.keys()
:
1const myFruits = ['kiwi', 'apple', 'kiwi', 'orange', 'kiwi', 'apple'];23 const unique = {};45 myFruits.forEach(item => {6 unique[item] = true;7 });89// Получаем массив из уникальных ключей10const uniqueArray = Object.keys(unique);1112console.log( uniqueArray);13// Array(3) [ "kiwi", "apple", "orange" ];
Как и в предыдущем примере можно создать специальную функцию, которая будет принимать на вход массив, а на выходе возвращать новый массив из уникальных значений исходного массива.
1const uniqueItems = (list) => {2 const unique = {};34 list.forEach(item => {5 unique[item] = true;6 });78 return Object.keys(unique);9}
Таким образом мы можем повторно использовать нашу новую функцию uniqueItems
в разных частях нашего кода с разными исходными массивами:
1const fruits = ['kiwi', 'apple', 'kiwi', 'orange', 'kiwi', 'apple'];23const fruitsUnique = uniqueItems(fruits);45console.log(fruitsUnique);6// Array(3) [ "kiwi", "apple", "orange" ];
Задача 3. Создать функцию, которая группирует студентов по возрасту.
На выходе требуется получить объект, где ключ - возраст, а значение - массив студентов, которые относятся к данной возрастной группе.
Исходный массив:
1const students = [2 { name: 'alex', age: 20 },3 { name: 'mike', age: 24 },4 { name: 'masha', age: 20 },5 { name: 'stas', age: 18 },6];
Требуется получить ответ в следующем формате:
1// '20': [{ name: 'alex', age: 20 }, { name: 'masha', age: 20 }],2// '24': [{ name: 'mike', age: 24 }],3// '18': [{ name: 'stas', age: 18 }],
Эту задачку мы также можем решить, используя цикл forEach
и пустой объект, в который будем добавлять каждый элемент массива (студент).
В качестве ключа будем использовать возраст.
Для каждого студента проверяем, был ли ранее добавлен ключ со значением его возраста в объект grouped
.
1const students = [2 { name: 'alex', age: 20 },3 { name: 'mike', age: 24 },4 { name: 'masha', age: 20 },5 { name: 'stas', age: 18 },6];78const grouped = {};910students.forEach(s => {1112 if (!grouped[s.age]) {13 // Ключ с возрастом отсутствует14 grouped[s.age] = [s];1516} else {17 grouped[s.age].push(s);18 }19});
Если ключ (s.age
) отсутствует, то добавляем его в объект grouped
.
В этом случае значением ключа будет объект текущего студента (переменная s) в массиве [s]
.
Если ключ ранее уже был добавлен в объект, то значение ключа уже содержит массив,
в который нам остается добавить текущий объект студента с помощью метода push
.
Задача 4.
Требуется написать функцию, которая отвечает следующим требованиям:
- Функция принимает 2 аргумента - массив из уникальных целых чисел и сумму в виде целого числа.
- Если сумма двух любых чисел массива из 1-го аргумента равна числу, которое приходит 2-м аргументом, функция должна вернуть новый массив из этих двух чисел в любом порядке.
- Если решения нет, вернуть пустой массив.
Итак, у нас есть исходный массив myNumbers
и целое число sum
:
1const myNumbers = [3, 5, -4, 8, 11, 1, -1, 6];2const sum = 10;
Результат работы нашей функции должен иметь следующий формат:
1// [-1, 11] или [11, -1] - так как -1 + 11 = 10;
Наша итоговая функция может выглядеть следующим образом:
1const findPairs = (nums, target) => {23 // Основной цикл4 for (let i = 0; i < nums.length; i++) {5 const numFirst = nums[i];67 // Вложенный цикл8 for (let j = i + 1; j < nums.length; j++) {9 const numSecond = nums[j];1011 // Условие12 if (numFirst + numSecond === target) {1314 // Условие выполняется15 return [numFirst, numSecond];16 }17 }18 }1920 // Условие не выполняется21 return [];22}
Наша функция findPairs
принимает на вход массив nums
и целое число target
.
Внутри функции мы создаем основной цикл, с помощью которого "бежим" по каждому элементу массива nums
, ничаная с 1-го элемента (индекс i = 0
).
Внутри основного цикла записываем последовательно каждый элемент массива nums
в переменную numFirst
.
Чтобы для каждого значения, которое мы записываем в переменную numFirst
получать
следующий за ним элемент массива, запускаем вложенный цикл. Этот цикл "стартует" со 2-го элемента массива nums
(индекс j = i + 1
).
Внутри вложенного цикла записываем каждое значение в переменную numSecond
.
Далее, внутри вложенного цикла проверяем, равняется ли сумма numFirst
и numSecond
переменной target
.
Если условие выполняется, возвращаем значения numFirst
и numSecond
внутри новго массива.
В противном случае функция возвращает пустой массив.
Запускаем функцию и выводим в лог результат:
1const result = findPairs(myNumbers, sum);23console.log(result);4// Array [ 11, -1 ]
Задача 5. Получить единый массив из любимых пицц каждого друга
Имеется исходный массив friends
:
1const friends = [2 { name: 'alex', pizzas: ['cheese', 'pepperoni'] },3 { name: 'mike', pizzas: ['salami', 'margarita'] },4 { name: 'stas', pizzas: ['meat'] },5 { name: 'anna', pizzas: ['fish'] }6];
Нужно получить результат в следующем формате:
1// ['cheese', 'pepperoni', 'salami', 'margarita', 'meat', 'fish'];
Для решения этой задачи можем использовать метод reduce
:
1const pizzas = friends.reduce((accum, current) => {2 return [...accum, ...current.pizzas];3}, []);
На старте, указываем, что начальное значение переменной accum
- пустой массив []
.
Далее, последовательно "бежим" по каждому элементу массива
и каждый раз возвращаем обновленное значение accum
.
Обновленное значение accum
это - массив, в который при каждой итерации добавляются:
- Все текущие элементы переменной
accum
, которые были добавлены в предыдущей итерации - Все пиццы из текущего элемента массива в переменной
current
:current.pizzas
Получаем результат и выводим его в лог:
1console.log(pizzas);2// Array(6) [ "cheese", "pepperoni", "salami", "margarita", "meat", "fish" ]
Задача 6. Записать строку (символы строки) в обратном порядке
Наше исходное строковое значение:
1const myStr = 'pizza';
От нас требуется получить строковое значение pizza
, записанное в обратном порядке:
1// azzip
Давайте рассмотрим 2 варианта записи строковых значений в обратном порядке.
Задача 6. Вариант 1 - используем цикл
1const myStr = 'pizza';23const reverseString = (str) => {4 const reversed = [];56 for (let i = str.length - 1; i >= 0; i--) {7 reversed.push(str[i]);8 };910 return reversed.join('');11};
Создаем функцию reverseString
, которая на вход принимает строковое значение в переменной str
.
Далее создаем цикл, который итерирует каждый символ строки в обратном порядке,
начиная с последнего элемента (индекс i = str.length - 1
).
При итерации каждый символ переменной str
последовательно добавляется в новый пустой массив reversed
.
После окончания работы цикла, массив reversed
трансформируется в строковое значение,
используя метод .join()
.
На выходе получаем символы строки pizza
, записанные в обратном порядке:
1const reverseResult = reverseString(myStr);23console.log(reverseResult);4// azzip
Задача 6. Вариант 2 - используем метод .split() и .reverse()
Чтобы записать строку в обратном порядке мы также можем использовать методы .split()
и .reverse()
.
1const reverseString2 = (str) => {2 return str.split('').reverse().join('');3};
Используя этот вариант, мы сначала используем метод .split()
, чтобы создать массив из строчного значения в переменной str
.
Даллее, по цепочке применяем к полученному массиву 2 метода:
- Метод
.reverse
, который меняет порядок элементов в массиве в обратном направлении (Записывает первый элемент последним, а последний — первым). - Метод
.join
, который объединяет элементы массива в строку. В методе.join()
указывается разделитель, который будет вставлен между элементами. В нашем случае - указываем пустые ковычки.join('')
.