Javascript 这是ES6在没有循环的情况下查找因子的最有效方法吗?

Javascript 这是ES6在没有循环的情况下查找因子的最有效方法吗?,javascript,arrays,ecmascript-6,factors,Javascript,Arrays,Ecmascript 6,Factors,我试图找到一种最不冗长的方法来查找数组中每个数字的因子,而不使用循环。我有一段ES6代码,我可以在.map中使用它来避免循环,但我不知道它在第二行中做了什么 我已经看过MDN上的.filter和.from方法,所以我们只是通过调用array()从一个iterable中浅层复制一个数组实例,看起来是空的,但之后我无法用英语描述它,这让我感到不安 let evens = [2,4,6,80,24,36]; 以下是我试图用英语解构/解释的ES6片段 const factor = number =&g

我试图找到一种最不冗长的方法来查找数组中每个数字的因子,而不使用循环。我有一段ES6代码,我可以在.map中使用它来避免循环,但我不知道它在第二行中做了什么

我已经看过MDN上的.filter和.from方法,所以我们只是通过调用array()从一个iterable中浅层复制一个数组实例,看起来是空的,但之后我无法用英语描述它,这让我感到不安

let evens = [2,4,6,80,24,36];
以下是我试图用英语解构/解释的ES6片段

const factor = number => Array
    .from(Array(number), (_, i) => i)
    .filter(i => number % i === 0)
所以我把它放在这张地图上

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人员。

数组(数字)
创建一个长度为
数字的空数组。现在,由于它是完全空的长度是不是真的有用呢。。。但是,如果您在其上调用
Array.from
,它会迭代所有索引(直到
number
),然后调用传递的回调并使用返回值构建一个新数组
(u,i)=>i
获取上一个值的索引(该值一直是
未定义的
),并将其作为值返回。因此,您会得到以下结果:

 number | Array.from
 0            | []
 1            | [0]
 2            | [0, 1]
 5            | [0, 1, 2, 3, 4]
如您所见,这将生成从0到编号的所有数字。现在,您只需过滤掉那些平均除数的值,这可以通过检查对零的模运算结果轻松完成:

  1 % 2 -> 1
  2 % 2 -> 0
  3 % 2 -> 1
  4 % 2 -> 0

我认为更有效的方法是使用发电机

另外一个好处是我认为代码更容易理解

let evens=[2,4,6,80,24,36];
函数*因子(n){
对于(设l=1;l{
返回数组.from(factor(number)).join(“,”);
}));

控制台日志(系数)这里有很多东西需要解包

首先,“不使用循环。”你能解释一下你的需求原因吗?并不是说我没有同情心,因为我通常避免显式循环,但您应该能够真正解释为什么要这样做。处理有序集合有两种根本不同的方法:迭代循环和递归。如果您不使用递归代码,可能有一个循环隐藏在某个地方。它可能被隐藏在
映射
过滤器
等中,这通常是一种改进,但该循环仍然存在

第二,这个片段的布局相当误导:

const factor=number=>Array
.from(数组(数),(u,i)=>i)
.filter(i=>number%i==0)
通常当许多行开始时,
.methodName(…)
这些方法中的每一个都对前一行提供的数据进行操作。但是
中的
这里只是
数组的静态方法
;像这样把它们分开是令人困惑的。这两种布局中的任何一种都会更好,许多其他布局也会更好:

const factor=number=>
数组.from(数组(数),(x,i)=>i)
.filter(i=>number%i==0)
const factor=number=>Array.from(
数组(编号),
(u,i)=>i
).filter(i=>number%i==0)
第三,正如评论和另一个答案所指出的,
Array.from
接受一个iterable和一个映射函数并返回一个数组,
Array(number)
将给您一个数组,该数组没有值,但其长度报告为
number
,因此将用作适当的iterable。有许多等效的方法可以编写,例如:

Array.from({length:number},(u,i)=>i)
[…数组(数字)].map((u,i)=>i)
第四,你提到:

const factors=evens.map((数字=>{
返回系数(数字)
}))
(排版固定)

虽然这并没有什么错,但您可能希望认识到,这可以写得更清晰

const factors=evens.map(因子)

最后,分解代码缺少一个主要的性能调整。当您真的可以成对找到因子时,您可以测试每个可能的值,最多测试
n
,最多测试
sqrt(n)
。这是一个重大区别。目前还没有已知的有效因子分解技术,这可能是一件好事,因为现代加密依赖于这是一个难题。但你很可能不想让事情变得更糟。

“我想避免循环”。。。为什么?就效率而言……使用
for
while
循环可能更有效……在需要更多代码的权衡下,我不应该使用“不使用循环”这一短语,而应该更明确地说“不显式地为循环或while循环编写代码”正如下面指出的,在from和filter方法中隐藏着循环。我非常感谢你的回答。我读过MDN“Array.from()方法从一个类似数组或iterable的对象创建一个新的浅拷贝数组实例”,它没有提到map函数,但我现在看到了。我仍然不清楚下划线在args中的用法,但我将继续阅读下面的…@BrutalBrutus:下划线只是一个变量。它和
$
是变量名中允许的字符。许多JS开发人员都遵循使用
\uuu
作为必须提供但未使用的参数的惯例。这来自于其他几种语言,这是实际语法。这里,使用了第二个参数,
i
,所以我们必须提供第一个参数,但是我们使用
\u
来表示我们不关心它。大会只进行了这么多,因为我们不能使用i