javascript - Is this the most efficient use of ES6 to find factors without a loop?
问题描述
I am trying to find the least verbose way to find the factors for each number in an array without using loops. I have a snippet of ES6 code that I could use in a .map to avoid a loop I think, but I'm at a loss as to what it is doing in the second line.
I've looked at the .filter and .from methods on MDN, so we're shallow copying an array instance from an iterable, seemingly empty by just calling Array(), but then I'm at a loss in describing it in English after that, which makes me feel uneasy.
let evens = [2,4,6,80,24,36];
Here's the ES6 snippet I'm trying to deconstruct/explain in English
const factor = number => Array
.from(Array(number), (_, i) => i)
.filter(i => number % i === 0)
so I dropped it into this .map like so
const factors = evens.map((number => {
return factors(number)
}))
console.log(factors)
I get an array of arrays of the factors as shown here
[ [ 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 ] ]
So...it works, but what is happening in that second line? I love that it is succinct, but when I try to reverse engineer it into non-ES6 I'm left wondering.
Thank you in advance, advanced ES6 folks.
解决方案
There are a number of things to unpack here.
First of all, "without using loops." Can you explain your reason for that requirement? Not that I'm unsympathetic, as I usually avoid explicit loops, but you should really be able to explain why you want to do this. There are two fundamentally different ways to process an ordered collection: iterative looping and recursion. If you're not using recursive code, there's probably a loop hiding somewhere. It might be buried inside a map
, filter
, etc., which is most often an improvement, but that loop is still there.
Second, the layout of this snippet is fairly misleading:
const factor = number => Array
.from(Array(number), (_, i) => i)
.filter(i => number % i === 0)
Usually when a number of lines start .methodName(...)
each of these methods operates on the data supplied by the previous line. But from
here is just a static method of Array
; separating them like this is confusing. Either of these would be better, as would many other layouts:
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)
Third, as comments and another answer have pointed out, Array.from
accepts an iterable and a mapping function and returns an array, and Array(number)
will give you an array with no values but which reports its length as number
, so will serve as an appropriate iterable. There are a number of equivalent ways one might write this, for instance:
Array.from({length: number}, (_, i) => i)
[...Array(number)].map((_, i) => i)
Fourth, you mention this:
const factors = evens.map((number => {
return factor(number)
}))
(typo fixed)
While there's nothing exactly wrong with this, you might want to recognize that this can be written much more cleanly as
const factors = evens.map(factor)
Finally, that factoring code is missing a major performance tweak. You test every possible value up to n
, when you really can find factors in pairs, testing only up to sqrt(n)
. That is a major difference. There is no known efficient factoring technique, which is probably a good thing as modern encryption depends upon this being a difficult problem. But you most likely don't want to make it much worse than it has to be.
推荐阅读
- cucumber - 将空手道测试报告发布到 Cucumber Open Report
- python - 如何根据 5 年平均值预测未来数据?
- api - 我想使用我的 Eventbrite 帐户凭据来登录我正在开发的 Web 应用程序,我该怎么做?
- bash - 在bash中比较当前日期和未来日期
- visual-studio-code - “terminal.integrated.shell.windows”是 Visual Studio Code 中的折旧错误
- c# - 使用 List<>.Contains 动态 Linq 到 EF
- python - 如何在第二个窗口中复制小部件
- python - How to limit the time input to only be accpetable within a timeperiod in Python
- python - 当我输入一个整数时 Python 脚本崩溃
- bash - 用于 QuantumEspresso scf 计算的 Bash 文件