Спрашивать [с работника] надо тогда, когда не поздно дать по рукам (Неизв.).

JavaScript. Поиск минимальных и максимальных значений в массиве объектов

FavoriteLoadingДобавить в избранное
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...
20 ноября 2017
JavaScript. Поиск минимальных и максимальных значений в массиве объектов
У нас есть массив из 100 000 объектов:

[
{x: 1, y: 14830},
{x: 2, y: 85055},
{x: 3, y: 03485},
{x: 4, y: 57885},
// ...
]

 

Значения Y рандомизированы. Как быстро найти минимальные и максимальные значения Y в нашем массиве?

 

Рассмотрим простой график ниже:

 

Как вы можете видеть, мы не смогли бы построить график без минимального и максимального значения x и y.

Значения X

Поскольку наши значения X постепенно увеличиваются, поиск минимального и максимального значения x очень прост:

Минимум: значение X первого объекта
Максимум: значение X последнего объекта

Наш минимум X всегда будет первой частью данных. Наш максимум X всегда будет последней частью данных.

Значения Y.

Наши значения Y являются случайными, поэтому поиск минимальных и максимальных значений Y немного сложнее. Опять же, рассмотрим наш простой граф:

Наши минимальные и максимальные значения Y могут быть в любом месте. Конечно, они могут быть первой и последней частью данных, но они также могут быть 4-м и 6-м частями данных, как в нашем примере выше. Нам нужна функция, которая проходит через каждый набор данных и находит значения Y

Тестирование.

Чтобы определить, какой вариант является самым быстрым, мы создадим большой массив из 100 000 объектов (со случайными данными), используя следующую функцию:

const data = []

for (let x = 1; x <= 100000; x++) {
  data.push({ x: x, y: Math.floor(Math.random() * (1000000)) })
}

// возвращает следующие данные:

[
  {x: 1, y: 14830},
  {x: 2, y: 85055},
  {x: 3, y: 03485},
  {x: 4, y: 57885},
  // ...
]

 

Решения.

Ниже приведены три возможных решения. Для области проекта потребовались два отдельных вызова функций: один для минимального значения Y и один для максимального значения Y. Для других проектов вы можете объединить только один вызов функции.

1. Используя метод reduce()

reduce() – удобный метод Array, который применяет функцию к накопителю и каждому элементу массива (слева направо), чтобы уменьшить его до одного значения. Ниже приведен простой пример.

let sum = [1, 2, 3].reduce((total, num) => total + num, 0);
// sum === 6

// [1, 2, 3].reduce((total, num) => total + num, 0)
// [1, 2, 3].reduce((0, 1) => 0 + 1)
// [2, 3].reduce((1, 2) => 1 + 2)
// [3].reduce((3, 3) => 3 + 3)
// 6

 

  1. Мы создаем переменную с именем sum и устанавливаем ее равной возвращаемому значению нашего метода reduce().
  2. Метод reduce() работает слева направо в нашем массиве. Он добавляет каждое num (число) в массиве к общему значению. 0 в конце обратного вызова указывает начальное значение для total.
  3. Начиная с 1, метод reduce() добавляет 1 к total, затем переходит к следующему значению в массиве (1 + 0).
  4. 2 добавляется к total (2 + 1).
  5. 3 добавляется к total (3 + 3), и возвращается total значение (6)

Имея это в виду, вот код, который мы использовали для получения минимального и максимального значений Y :

function getMinY () {
    return data.reduce((min, p) => py < min ? py : min, data[0].y); 
}

function getMaxY () { 
    return data.reduce((max, p) => py > max ? py : max, data[0].y);
}

 

Давайте пройдем через getMinY()

Используя метод reduce() мы проверяем, меньше ли текущее значение Y массива, чем минимальное значение, сохраненное в функции reduce(). Если это так, мы возвращаем текущее значение Y используя p.y. Если это не так, возвращается сохраненное значение min. Наконец, у нас есть начальное значение (для первой итерации функции), заданное первым Y в наборе данных.

2. Используя map(), Math и оператор spread

Читатель прокомментировал следующую альтернативу:

function getYs (){
     return data.map(d => dy);
}
function getMinY (){
     return Math.min(...getYs());
}
function getMaxY (){
     return Math.max(...getYs());
}

 

Мы начинаем с функции, которая получает все наши значения Y, поэтому нам не нужно иметь дело с объектами. Используя встроенную Array.prototype.map(), мы берем все наши значения Y и вставляем их в новый массив чисел.

Теперь, когда у нас есть простой массив чисел, мы используем Math.min() или Math.max() чтобы вернуть значения min/max из нашего нового массива значений Y. Оператор spread позволяет нам вставлять массив во встроенную функцию.

3. Почему не оба?

Это приводит к среднему основному решению, в котором мы используем как reduce(), так и Math.min() и Math.max() :

function getMinY (){
     return data.reduce((min, b) => Math.min(min, by), data[0].y);
}
function getMaxY (){
     return data.reduce((max, b) => Math.max(max, by), data[0].y);
}

 

Вариант 3. Как вы можете видеть, очень похож на вариант 1. Единственное отличие заключается в том, что мы заменили p.y < min ? p.y : min на Math.min(min, b.y). Эти два фрагмента кода делают то же самое.

Самый быстрый вариант?

Мы лично считаем, что третье решение является самым изящным и легким для чтения, но, к сожалению, это не самое быстрое решение. Мы использовали jsperf для проверки производительности всех трех решений:

  • Вариант 1 на сегодняшний день является самым быстрым.
  • Вариант 2 на ~ 87% медленнее, чем Вариант 1.
  • Вариант 3 на ~ 57% медленнее, чем Вариант 1.

Если скорость – это все, что вам нужно, другое решение вытесняет все три из вышеперечисленных. Одна функция с циклом for в два раза быстрее, чем опция номер один выше:

function findMinMax(arr) {
  let min = arr[0].y, max = arr[0].y;

  for (let i = 1, len=arr.length; i < len; i++) {
    let v = arr[i].y;
    min = (v < min) ? v : min;
    max = (v > max) ? v : max;
  }

  return [min, max];
}

 

 

Как вы думаете?

Есть другое решение? Думайте, что одно решение лучше, чем другие? Дайте нам знать в комментариях.

 

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Просмотров: 97

Если статья понравилась, то поделитесь ей в социальных сетях:

Читайте также

    Добавить комментарий

    Войти с помощью: 

    Ваш e-mail не будет опубликован. Обязательные поля помечены *

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам:

    Заполните форму и наш менеджер перезвонит Вам в самое ближайшее время!

    badge
    Обратный звонок 1
    Отправить
    galka

    Спасибо! Ваша заявка принята

    close
    galka

    Спасибо! Ваша заявка принята

    close