13 полезных приёмов по работе с массивами в JavaScript, которые могут вам пригодиться

Автор оригинала: Radoslaw Fabisiak
  • Перевод
Массивы являются одной из самых популярных структур данных в JavaScript, потому что они используются для хранения данных. Кроме этого, массивы дают много возможностей для работы с этими самыми данными. Понимая, что для тех, кто находится в начале пути изучения JavaScript, массивы являются одной из самых основных тем, в этой статье я хотел бы познакомить вас с некоторыми полезными трюками, о которых вы могли не знать. Давайте начнем.

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 и которые стоит изучить не только для работы с массивами, но и для других структур данных. Я надеюсь, что вам понравились решения, представленные в статье, и вы будете использовать их для улучшения процесса разработки.

Приятного написания кода!
Поделиться публикацией

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 40

    +7

    Помимо того, что почти половина "трюков" заключается в использовании стандартных и вполне себе известных методов массивов вроде reverse() и splice(), статья ещё и вводит некоторые сомнительные ограничения вроде — как трансформировать массив без map(). Зачем? Какое у from() преимущество, кроме менее лаконичной записи? Чем не угодили concat(), который работает быстрее спреда и для более чем двух массивов опять же позволяет получить более короткую запись?)

      0
      Перечитайте первый абзац еще раз. Эта статья рассчитана на новичков в программировании, которые, возможно, еще не знают все стандартные и известные методы. Да и метка стоит «beginners». Я не автор, я просто перевел ее)
        +1

        Зря вы выбрали именно эту статью. Скажем там в одном из примеров O(n^2) там где хватит O(n). Зачем такому учить новичков? Метод .reduce описан чуть менее чем никак, просто "магия". Вообще не упомянуто про то, что .reverse и .sort мутируют массив (и даже даётся ложная иллюзия того, что это не так, за счёт присваивания значения новой переменной). Вообще статья попахивает, если честно.

          0
          Согласен с Вами. Надо ответственнее подходить к выбору статьи для переводов, я это понял на своем опыте)
        +1
        Зачем? Какое у from() преимущество, кроме менее лаконичной записи?

        Он работает с итерируемыми обектами, не являющимися массивами и соответственно не имеющими метода map. Например DOM API возвращает всё что угодно, но не массивы, к сожалению.

          0

          Вы правы. Жаль только это в комментариях, а не в статье)

            +1
            Он работает с итерируемыми обектами

            Не только с итерируемыми, но и с массивоподобными. Например {length:3}
          0
          Ожидание: 13 полезных приёмов.
          Реальность:
          3. Как трансформировать массив, не используя метод map()
          5. Как преобразовать массив в объект
          12. Метод lastIndexOf()
          Причём только 10-й пункт ушёл лишь чуточку дальше использования примеров из документации.
            +4
            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]


            Автор охренел? Нахрена было создавать набор, если потом всё равно проверяем 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));
            
              +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, и на основании этого использовать либо первый вариант, либо второй.

                +1
                В условии не было сказано, что результат не должен содержать повторов.
                  0
                  Согласен, явно этого сказано не было. Только решение, которое вы предлагаете, может давать разные результаты, если поменять местами входные массивы. Как-то несолидно, не находите?
                    +1
                    В оригинале написано «Find the intersection of two arrays». И в этом случае, операция пересечения множеств коммутативна. Зачем было переводить как «Как найти общие элементы двух массивов» непонятно.
                      0
                      Это мой косяк, спасибо за замечание, поправлю. Я посчитал, что «общие элементы» звучит понятнее, чем «пересечение». Но в итоге получился немного другой смысл.
                0
                Я на полминуты завис от слова «набор». Множество же.
                0
                прошу прощения за нубский вопрос, я не спец в JavaScript. Хотел спросить по поводу объектов. Таки в JavaScript словарь называется объектом, или это особенности перевода?
                  +1
                  Простите, какой язык Вам родной? Просто не вполне понятно, что Вы называете словарём.
                    0
                    python.
                    А словарем я называю то, что получают в 5 совете:
                    {0: 'banana', 1: 'apple', 2: 'orange', 3: 'watermelon', 4: 'apple', 5: 'orange', 6: 'grape', 7: 'apple'}
                      +2
                      Ну, если пользоваться терминологией питона и сильно упрощать, то можно сказать, что в JS любой объект — словарь. При этом объектом, в смысле ООП он быть не перестаёт.
                        0
                        хм, ну еще мне близок C++ с его ассоциативными массивами, те же словари, но чтобы даже с конструктором — это словарь, интересно конечно. Спасибо за пояснение
                          +1
                          Добавлю, что объект в JavaScript похож на «классический » словарь (std::map в c++) методами доступа к полям (в JavaScript они называются свойствами — properties), но всё-же словарём не является. Есть ограничения/тонкости. Хотя, до появления Map, объекты часто использовались в качестве словарей с известными ограничениями.
                            0
                            да, аналогию с map понял, спасибо. Все равно хотел когда-то начать знакомиться с JS, видимо пора начать :)
                              0

                              Скорее всего вы имели в виду std::unordered_map

                            +1
                            Объекты в жс это в первом приближении словари, да. Причем ключи всегда строки:

                            const a = {1.0: 2.0}
                            Object.keys(a) // [ "1" ]
                            

                            Впрочем, есть и хорошие человеческие словари.
                              0
                              да, интересно автоматическое приведение типа, ох… Спасибо, почитаю подробнее
                        +2
                        В пятом совете в итоге получится объект
                        { '0': 'banana', '1': 'apple', '2': 'orange', '3': 'watermelon', '4': 'apple', '5': 'orange', '6': 'grape', '7': 'apple' }
                        . То-есть, числовые ключи преобразуются в строки. Кстати, в оригинале та же неточность.
                          0
                          да, по ответу printf понял, что ключи приводятся к строке, я копировал пример из статьи
                          –1
                          4. Чем это отличается от arr = []? Вообще не представляю нафига усложнять этот пример до написания лишнего lenght.
                          5 и 8 — это спасибо спреду скажите, лучше бы пример на ES5 дали.
                          А, ну и пример с использованием мат.рандом вообще банальность дикая, как по мне.

                          Это больше на шпаргалку по языку «для себя» похоже, чем на статью для хабра, уж извините.
                            –1
                            4. Там массив изменяется по ссылке, а у вас нет
                              –2
                              Какая мне разница что там изменится по ссылке, если меня волнует, в первую очередь, на что указывает указатель?
                                0

                                It depends. Зависит от задачи. Если на ваш массив уже есть где-то другие ссылки, и вы желаете чтобы они всё также вели на актуальный набор данных, то вам очень даже важно ничего не поломать.

                                  0
                                  Если на мой массив где-то есть другие ссылки, с какой целью мне понадобится делать ему lenght = 0 и сохранять при этом содержимое?

                                  Приведите не синтетический пример.
                                    –1
                                    с какой целью мне понадобится делать ему lenght = 0

                                    дабы обеспечить консистентность данных при обнулении коллекции.


                                    Приведите не синтетический пример

                                    Вы же пишете, что у вас 10+ лет опыта в программировании. Это такой троллинг?

                                      0
                                      Ещё раз, зачем мне обеспечивать некую консистентность данных, если я, по сути, обнуляю массив.

                                      Это такой троллинг?

                                      Вы либо сами запутались в чуши, которую пишете, либо не в состоянии собственные заявления аргументировать.
                                        0

                                        Хорошо, на этом и порешим.

                              0
                              Согласен, материал, возможно, не самый интересный и востребованный. Я просто увидел количество положительных комментариев под оригинальным постом и подумал, что перевести не самая плохая идея. Если хоть одному человеку этот перевод окажется полезным, я буду рад.
                              0
                              А как оставить те, что НЕ уникальные?)
                                0

                                Дружище, ну хоть вычитай то, что написал. Как «пере» массив, как полуь массив, это же позор.

                                  0
                                  Спасибо за замечание :) Я использую гугл-расширение Multi-higlight, которое подсвечивает внесенные в список слова. В этом списке в том числе есть слова «вам», «чит», «вернуть», «очен». И похоже из-за этого расширения при редактировании статьи подсвеченные слова были выброшены из текста. В общем, нашелся интересный баг)
                                  0
                                  воистину функциональщина топ

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                  Самое читаемое