Это наиболее эффективное использование ES6 для поиска факторов без петли? - PullRequest
0 голосов
/ 01 апреля 2019

Я пытаюсь найти наименее подробный способ найти факторы для каждого числа в массиве без использования циклов. У меня есть фрагмент кода ES6, который я мог бы использовать в .map, чтобы избежать цикла, я думаю, но я в растерянности относительно того, что он делает во второй строке.

Я посмотрел на методы .filter и .from в MDN, поэтому мы копируем экземпляр массива из повторяемого, казалось бы, пустого, просто вызывая Array (), но потом я не могу описать после этого на английском, что заставляет меня чувствовать себя неловко.

let evens = [2,4,6,80,24,36];

Вот фрагмент ES6, который я пытаюсь деконструировать / объяснить по-английски

const factor = number => Array
    .from(Array(number), (_, i) => i)
    .filter(i => number % i === 0)

поэтому я поместил его в .map вот так

const factors = evens.map((number => {
    return factors(number)
}))

console.log(factors)

Я получаю массив массивов факторов, как показано здесь

[ [ 1 ],
  [ 1, 2 ],
  [ 1, 2, 3 ],
  [ 1, 2, 4, 5, 8, 10, 16, 20, 40 ],
  [ 1, 2, 3, 4, 6, 8, 12 ],
  [ 1, 2, 3, 4, 6, 9, 12, 18 ] ]

Итак ... это работает, но что происходит во второй строке? Мне нравится, что он лаконичен, но когда я пытаюсь преобразовать его в не-ES6, я задаюсь вопросом.

Заранее спасибо, продвинутые ребята из ES6.

Ответы [ 3 ]

1 голос
/ 02 апреля 2019

Здесь можно распаковать несколько вещей.

Прежде всего, "без использования петель".Можете ли вы объяснить причину этого требования?Не то чтобы я не сочувствую, поскольку я обычно избегаю явных циклов, но вы действительно должны объяснить , почему вы хотите это сделать.Существует два принципиально разных способа обработки упорядоченной коллекции: итеративный цикл и рекурсия.Если вы не используете рекурсивный код, возможно, где-то скрывается цикл.Он может быть скрыт внутри map, filter и т. Д., Что чаще всего является улучшением, но этот цикл все еще существует.

Во-вторых, компоновка этого фрагмента вводит в заблуждение:

const factor = number => Array
    .from(Array(number), (_, i) => i)
    .filter(i => number % i === 0)

Обычно, когда начинается несколько строк .methodName(...), каждый из этих методов работает с данными, предоставленными предыдущей строкой.Но from здесь просто статический метод Array;разделяя их так, это сбивает с толку.Любой из них был бы лучше, как и многие другие макеты:

const factor = number => 
    Array.from(Array(number), (_, i) => i)
    .filter(i => number % i === 0)
const factor = number => Array.from(
    Array(number), 
    (_, i) => i
).filter(i => number % i === 0)

В-третьих, как уже отмечалось в комментариях и другом ответе, Array.from принимает итеративную функцию и функцию отображения и возвращает массиви Array(number) даст вам массив без значений, но который сообщит, что его длина равна number, поэтому будет служить подходящей итерацией.Существует несколько эквивалентных способов написать это, например:

Array.from({length: number}, (_, i) => i)
[...Array(number)].map((_, i) => i)

В-четвертых, вы упомянули это:

const factors = evens.map((number => {
    return factor(number)
}))

(опечатка исправлена)

Хотя в этом нет ничего плохого, вы, возможно, захотите признать, что это можно записать гораздо более четко, как

const factors = evens.map(factor)

Наконец, в этом коде факторинга отсутствует серьезная настройка производительности.Вы проверяете каждое возможное значение до n, когда вы действительно можете найти факторы в парах, тестируете только до sqrt(n).Это серьезная разница.Не существует известного эффективного метода факторинга, что, вероятно, является хорошей вещью, поскольку современное шифрование зависит от того, является ли это сложной проблемой.Но вы, скорее всего, не хотите делать это намного хуже, чем должно быть.

0 голосов
/ 02 апреля 2019

Я думаю, что более эффективным способом было бы использование генераторов.

В качестве бонуса я думаю, что код легче понять.

let evens = [2,4,6,80,24,36];

function* factor(n) {
  for (let l = 1; l < n; l += 1) {
    if (n % l === 0) yield l;
  }
}

const factors = evens.map((number => {
  return Array.from(factor(number)).join(", ");
}));

console.log(factors);
0 голосов
/ 02 апреля 2019

Array(number) создает пустой массив длиной number. Теперь, когда он полностью пуст, длина пока не очень полезна ... если вы, однако, вызываете Array.from, он выполняет итерацию по всем индексам (до number), а затем вызывает переданный обратный вызов и создает новый массив с возвращаемыми значениями. (_, i) => i берет индекс предыдущего значения (который постоянно равен undefined) и возвращает его в качестве значения. Поэтому вы получаете следующие результаты:

 number | Array.from
 0            | []
 1            | [0]
 2            | [0, 1]
 5            | [0, 1, 2, 3, 4]

Как видите, это генерирует все числа от 0 до number. Теперь вам просто нужно отфильтровать те, которые равномерно делят number, что легко сделать, проверив результат операции по модулю с нулями:

  1 % 2 -> 1
  2 % 2 -> 0
  3 % 2 -> 1
  4 % 2 -> 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...