1. Как в массиве оставить только уникальные значения
Это очень популярный вопрос во время интервью на позицию Javascript-разработчика. Вот быстрое и простое решение этой задачки. Для начала вам нужно получить уникальные значения массива, для этого можно использовать
new Set()
(прим. перев.: структура данных Set хранит только уникальные значения). Далее нужно преобразовать структуру данных Set в массив. Я хочу познакомить вас с двумя способами, как это можно сделать: первый – с помощью метода from()
, второй – с помощью оператора spread ("…"
).const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
// Первый метод
const uniqueFruits = Array.from(new Set(fruits));
console.log(uniqueFruits); // вернет ['banana', 'apple', 'orange', 'watermelon', 'grape']
// Второй метод
const uniqueFruits2 = [...new Set(fruits)];
console.log(uniqueFruits2); // вернет ['banana', 'apple', 'orange', 'watermelon', 'grape']
Легко, правда?
2. Как заменить значения в массиве
Бывают такие ситуации, когда нужно заменить значения в массиве другими значениями. Для этого существует хороший метод, о котором вы, возможно, не знали – метод
splice(start, value to remove, values to add)
, где start
– номер индекса, начиная с которого мы хотим удалить элементы массива, value to remove
– число элементов, которые мы хотим удалить, а values to add
– элементы, которые мы хотим вставить на место удаленных:const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
fruits.splice(0, 2, 'potato', 'tomato');
console.log(fruits); // вернет ["potato", "tomato", "orange", "watermelon", "apple", "orange", "grape", "apple"]
3. Как трансформировать массив, не используя метод map()
Наверное, все знают метод массива
map()
, но есть и другое решение, которое может быть использовано для получения аналогичного эффекта и чистого кода. Для этого мы можем воспользоваться методом from()
:const friends = [
{ name: 'John', age: 22 },
{ name: 'Peter', age: 23 },
{ name: 'Mark', age: 24 },
{ name: 'Maria', age: 22 },
{ name: 'Monica', age: 21 },
{ name: 'Martha', age: 19 },
]
const friendsNames = Array.from(friends, ({name}) => name);
console.log(friendsNames); // вернет ['John', 'Peter', 'Mark', 'Maria', 'Monica', 'Martha']
4. Как быстро очистить массив
Например, у нас есть массив, в котором много элементов. Нам нужно его очистить (неважно для какой цели), при этом мы не хотим удалять элементы один за другим. Это очень просто сделать одной строчкой кода. Чтобы очистить массив, нам нужно установить длину массива в 0, и всё!
const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
fruits.length = 0;
console.log(fruits); // вернет []
5. Как преобразовать массив в объект
Бывает такая ситуация: у нас есть массив, но нам нужен объект (опять неважно для какой цели) с этими данными, и самый быстрый способ преобразовать массив в объект – это использовать оператор spread (
"..."
):const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
const fruitsObj = { ...fruits };
console.log(fruitsObj); // вернет {0: 'banana', 1: 'apple', 2: 'orange', 3: 'watermelon', 4: 'apple', 5: 'orange', 6: 'grape', 7: 'apple'}
6. Как заполнить массив одинаковыми значениями
Бывают разные ситуации, когда мы хотим создать массив и заполнить его некоторыми значениями, или нам нужен массив с одинаковыми значениями. Метод
fill()
для подобных задач является отличным решением:const newArray = new Array(10).fill('1');
console.log(newArray); // вернет ["1", "1", "1", "1", "1", "1", "1", "1", "1", "1"]
7. Как объединить более двух массивов
Вы знаете, как объединить массивы в один, не используя метод
concat()
? Существует простой способ объединить любое количество массивов в один массив одной строчкой кода. Как вы, вероятно, уже поняли, оператор spread ("..."
) является довольно полезным инструментом при работе с массивами, как и в этом случае:const fruits = ['apple', 'banana', 'orange'];
const meat = ['poultry', 'beef', 'fish'];
const vegetables = ['potato', 'tomato', 'cucumber'];
const food = [...fruits, ...meat, ...vegetables];
console.log(food); // вернет ["apple", "banana", "orange", "poultry", "beef", "fish", "potato", "tomato", "cucumber"]
8. Как найти пересечение двух массивов
С этой задачей вы можете столкнуться на любом JavaScript-собеседовании, потому что ее решение показывает ваши знания методов массива, а также то, как вы мыслите. Чтобы найти общие значения двух массивов, мы будем использовать один из ранее рассмотренных методов в этой статье, чтобы убедиться, что значения в массиве, который мы проверяем, не дублируются. Кроме этого, мы воспользуемся методами
filter()
и includes()
. В результате мы получим массив с элементами, которые представлены в обоих массивах:const numOne = [0, 2, 4, 6, 8, 8];
const numTwo = [1, 2, 3, 4, 5, 6];
const duplicatedValues = [...new Set(numOne)].filter(item => numTwo.includes(item));
console.log(duplicatedValues); // вернет [2, 4, 6]
9. Как удалить ложные значения из массива
Для начала, давайте определим ложные значения. В Javascript ложными значениями являются:
false
, 0, "", null
, NaN
и undefined
. Теперь мы можем выяснить, как удалить такие значения из нашего массива. Для достижения этой цели нам потребуется метод filter()
:const mixedArr = [0, 'blue', '', NaN, 9, true, undefined, 'white', false];
const trueArr = mixedArr.filter(Boolean);
console.log(trueArr); // вернет ["blue", 9, true, "white"]
10. Как получить рандомное значение массива
Иногда нам нужно выбрать рандомное значение массива. Чтобы решение было простым, коротким и быстрым, мы можем получить случайный номер индекса в соответствии с длиной массива. Посмотрите на этот пример:
const colors = ['blue', 'white', 'green', 'navy', 'pink', 'purple', 'orange', 'yellow', 'black', 'brown'];
const randomColor = colors[(Math.floor(Math.random() * (colors.length)))];
console.log(randomColor); // вернет рандомный цвет из массива
11. Как развернуть массив в обратную сторону
Когда нам нужно «перевернуть» наш массив, нет необходимости создавать его через сложные циклы и функции, потому что есть простой метод массива
reverse()
, который делает все это за нас, и одной строчкой кода мы можем «перевернуть» наш массив:const colors = ['blue', 'white', 'green', 'navy', 'pink', 'purple', 'orange', 'yellow', 'black', 'brown'];
const reversedColors = colors.reverse();
console.log(reversedColors); // вернет ["brown", "black", "yellow", "orange", "purple", "pink", "navy", "green", "white", "blue"]
12. Метод lastIndexOf()
В JavaScript есть интересный метод
lastIndexOf(elem)
, который позволяет найти индекс последнего вхождения элемента elem
. Например, если наш массив имеет дублированные значения, мы можем найти позицию последнего вхождения в него. Взгляните на следующий пример кода:const nums = [1, 5, 2, 6, 3, 5, 2, 3, 6, 5, 2, 7];
const lastIndex = nums.lastIndexOf(5);
console.log(lastIndex); // вернет 9
13. Как просуммировать все значения в массиве
Еще один популярный вопрос во время собеседования на позицию JavaScript-разработчика. Сумму всех элементов можно найти одной строчкой кода, если знать метод
reduce()
:const nums = [1, 5, 2, 6];
const sum = nums.reduce((x, y) => x + y);
console.log(sum); // вернет 14
Заключение
В этой статье я познакомил вас с 13 полезными приёмами, которые помогут вам писать чистый и краткий код. Кроме этого, не забывайте, что есть много различных трюков, которые вы можете использовать в Javascript и которые стоит изучить не только для работы с массивами, но и для других структур данных. Я надеюсь, что вам понравились решения, представленные в статье, и вы будете использовать их для улучшения процесса разработки.
Приятного написания кода!
Комментарии (40)
Aingis
15.11.2019 21:27Ожидание: 13 полезных приёмов.
Реальность:
3. Как трансформировать массив, не используя метод map()
Причём только 10-й пункт ушёл лишь чуточку дальше использования примеров из документации.
5. Как преобразовать массив в объект
12. Метод lastIndexOf()
Zenitchik
15.11.2019 21:54+3const numOne = [0, 2, 4, 6, 8, 8]; const numTwo = [1, 2, 3, 4, 5, 6]; const duplicatedValues = [...new Set(numOne)].filter(item => numTwo.includes(item)); console.log(duplicatedValues); // вернет [2, 4, 6]
Автор охренел? Нахрена было создавать набор, если потом всё равно проверяем includes в массиве?
const numOne = [0, 2, 4, 6, 8, 8]; const numTwo = [1, 2, 3, 4, 5, 6]; const mySet = new Set(numOne); const duplicatedValues = numTwo.filter(value => mySet.has(item));
yarick123
15.11.2019 22:59+1Только всё-же лучше два набора, чтобы исключить дублирование элементов из numTwo. Ваш код, если поправить опечатки, в отличие от оригинала, для
const numOne = [0, 2, 4, 6, 8, 8]; const numTwo = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1];
заполнит duplicatedValues так: [ 2, 4, 6, 4, 2 ]
Вариант с двумя наборами:const numOne = [0, 2, 4, 6, 8, 8]; const numTwo = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]; const mySet = new Set(numOne); const duplicatedValues = [...new Set(numTwo.filter(item => mySet.has(item)))]; console.log(duplicatedValues); // вернет [2, 4, 6]
Ну или вначале из numTwo сделать набор.
Для больших массивов можно сравнить количество элементов в mySet и numTwo, и на основании этого использовать либо первый вариант, либо второй.Zenitchik
15.11.2019 23:10+1В условии не было сказано, что результат не должен содержать повторов.
yarick123
15.11.2019 23:27-1Согласен, явно этого сказано не было. Только решение, которое вы предлагаете, может давать разные результаты, если поменять местами входные массивы. Как-то несолидно, не находите?
igormich88
16.11.2019 00:07В оригинале написано «Find the intersection of two arrays». И в этом случае, операция пересечения множеств коммутативна. Зачем было переводить как «Как найти общие элементы двух массивов» непонятно.
gaiazovr Автор
16.11.2019 09:01Это мой косяк, спасибо за замечание, поправлю. Я посчитал, что «общие элементы» звучит понятнее, чем «пересечение». Но в итоге получился немного другой смысл.
DollaR84
15.11.2019 23:06прошу прощения за нубский вопрос, я не спец в JavaScript. Хотел спросить по поводу объектов. Таки в JavaScript словарь называется объектом, или это особенности перевода?
Zenitchik
15.11.2019 23:12+1Простите, какой язык Вам родной? Просто не вполне понятно, что Вы называете словарём.
DollaR84
15.11.2019 23:16python.
А словарем я называю то, что получают в 5 совете:
{0: 'banana', 1: 'apple', 2: 'orange', 3: 'watermelon', 4: 'apple', 5: 'orange', 6: 'grape', 7: 'apple'}Zenitchik
15.11.2019 23:21+1Ну, если пользоваться терминологией питона и сильно упрощать, то можно сказать, что в JS любой объект — словарь. При этом объектом, в смысле ООП он быть не перестаёт.
DollaR84
15.11.2019 23:26хм, ну еще мне близок C++ с его ассоциативными массивами, те же словари, но чтобы даже с конструктором — это словарь, интересно конечно. Спасибо за пояснение
yarick123
15.11.2019 23:46+1Добавлю, что объект в JavaScript похож на «классический » словарь (std::map в c++) методами доступа к полям (в JavaScript они называются свойствами — properties), но всё-же словарём не является. Есть ограничения/тонкости. Хотя, до появления Map, объекты часто использовались в качестве словарей с известными ограничениями.
DollaR84
16.11.2019 00:30да, аналогию с map понял, спасибо. Все равно хотел когда-то начать знакомиться с JS, видимо пора начать :)
printf
15.11.2019 23:56+1Объекты в жс это в первом приближении словари, да. Причем ключи всегда строки:
const a = {1.0: 2.0} Object.keys(a) // [ "1" ]
Впрочем, есть и хорошие человеческие словари.DollaR84
16.11.2019 00:32да, интересно автоматическое приведение типа, ох… Спасибо, почитаю подробнее
yarick123
15.11.2019 23:54+2В пятом совете в итоге получится объект
. То-есть, числовые ключи преобразуются в строки. Кстати, в оригинале та же неточность.{ '0': 'banana', '1': 'apple', '2': 'orange', '3': 'watermelon', '4': 'apple', '5': 'orange', '6': 'grape', '7': 'apple' }
Psychosynthesis
16.11.2019 02:204. Чем это отличается от arr = []? Вообще не представляю нафига усложнять этот пример до написания лишнего lenght.
5 и 8 — это спасибо спреду скажите, лучше бы пример на ES5 дали.
А, ну и пример с использованием мат.рандом вообще банальность дикая, как по мне.
Это больше на шпаргалку по языку «для себя» похоже, чем на статью для хабра, уж извините.Finesse
16.11.2019 03:354. Там массив изменяется по ссылке, а у вас нет
Psychosynthesis
17.11.2019 21:44-2Какая мне разница что там изменится по ссылке, если меня волнует, в первую очередь, на что указывает указатель?
faiwer
17.11.2019 22:57It depends. Зависит от задачи. Если на ваш массив уже есть где-то другие ссылки, и вы желаете чтобы они всё также вели на актуальный набор данных, то вам очень даже важно ничего не поломать.
Psychosynthesis
18.11.2019 11:53Если на мой массив где-то есть другие ссылки, с какой целью мне понадобится делать ему lenght = 0 и сохранять при этом содержимое?
Приведите не синтетический пример.faiwer
18.11.2019 12:16-1с какой целью мне понадобится делать ему lenght = 0
дабы обеспечить консистентность данных при обнулении коллекции.
Приведите не синтетический пример
Вы же пишете, что у вас 10+ лет опыта в программировании. Это такой троллинг?
Psychosynthesis
18.11.2019 19:14Ещё раз, зачем мне обеспечивать некую консистентность данных, если я, по сути, обнуляю массив.
Это такой троллинг?
Вы либо сами запутались в чуши, которую пишете, либо не в состоянии собственные заявления аргументировать.
gaiazovr Автор
16.11.2019 09:26Согласен, материал, возможно, не самый интересный и востребованный. Я просто увидел количество положительных комментариев под оригинальным постом и подумал, что перевести не самая плохая идея. Если хоть одному человеку этот перевод окажется полезным, я буду рад.
ganqqwerty
16.11.2019 10:35Дружище, ну хоть вычитай то, что написал. Как «пере» массив, как полуь массив, это же позор.
gaiazovr Автор
16.11.2019 11:29Спасибо за замечание :) Я использую гугл-расширение Multi-higlight, которое подсвечивает внесенные в список слова. В этом списке в том числе есть слова «вам», «чит», «вернуть», «очен». И похоже из-за этого расширения при редактировании статьи подсвеченные слова были выброшены из текста. В общем, нашелся интересный баг)
andres_kovalev
Помимо того, что почти половина "трюков" заключается в использовании стандартных и вполне себе известных методов массивов вроде reverse() и splice(), статья ещё и вводит некоторые сомнительные ограничения вроде — как трансформировать массив без map(). Зачем? Какое у from() преимущество, кроме менее лаконичной записи? Чем не угодили concat(), который работает быстрее спреда и для более чем двух массивов опять же позволяет получить более короткую запись?)
gaiazovr Автор
Перечитайте первый абзац еще раз. Эта статья рассчитана на новичков в программировании, которые, возможно, еще не знают все стандартные и известные методы. Да и метка стоит «beginners». Я не автор, я просто перевел ее)
faiwer
Зря вы выбрали именно эту статью. Скажем там в одном из примеров O(n^2) там где хватит O(n). Зачем такому учить новичков? Метод
.reduce
описан чуть менее чем никак, просто "магия". Вообще не упомянуто про то, что.reverse
и.sort
мутируют массив (и даже даётся ложная иллюзия того, что это не так, за счёт присваивания значения новой переменной). Вообще статья попахивает, если честно.gaiazovr Автор
Согласен с Вами. Надо ответственнее подходить к выбору статьи для переводов, я это понял на своем опыте)
vintage
Он работает с итерируемыми обектами, не являющимися массивами и соответственно не имеющими метода map. Например DOM API возвращает всё что угодно, но не массивы, к сожалению.
andres_kovalev
Вы правы. Жаль только это в комментариях, а не в статье)
Zenitchik
Не только с итерируемыми, но и с массивоподобными. Например {length:3}