在 JavaScript 中从 1..20 创建整数数组的最简单方法
Posted
技术标签:
【中文标题】在 JavaScript 中从 1..20 创建整数数组的最简单方法【英文标题】:Tersest way to create an array of integers from 1..20 in JavaScript 【发布时间】:2011-09-12 01:44:18 【问题描述】:创建这个数组最简单的方法是什么:
var x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
例如,for
循环:
var x = [];
for (var i=1;i<=20;i++)
x.push(i);
或while
循环:
var x = [], i = 1, endInt = 20;
while (i <= endInt)
x.push(i);
i++;
是否还有其他更简洁的示例 - 换句话说 - 更少的代码?我在想像在 Ruby 中的东西,我相信等效代码就像1..20
一样简单。我不知道 javascript 中的语法,但我想知道是否有更短的方法来做同样的事情。
更新:我没有考虑删除分号或var
以获得问题的答案,但我不得不承认这个问题暗示了这一点。我对算法比对字节更感兴趣。对不起,如果我不清楚!另外,把它变成一个函数也很简单,只需在它周围拍一下function range(start, end) /* guts here */
就可以了。问题是“胆量”是否有新的方法。
【问题讨论】:
代码简洁是否重要,或者这只是一个思想实验? 真正的思想实验比什么都重要。我正在创建一个数组并实际上在考虑 php,我可以在其中执行var $x = range(1, 20);
... 就像,为什么不使用 JavaScript?
为什么不在JS中创建函数range()
并使用它呢?
push()
方法在这里实际上不是很聪明,因为动态数组增长。如果您事先知道字段的数量,则应使用大小显式初始化并通过索引填充字段:x[i-start_i] = i;
不禁认为 svicks 的评论是正确的答案。毕竟是JS。
【参考方案1】:
最喜欢的方法
2015 年 9 月 13 日更新:
刚刚想出了这个适用于支持 ES6 标准的浏览器的新方法:
> Array(5).fill().map((x,i)=>i)
[0, 1, 2, 3, 4]
注意上面做了一点额外的工作(用undefined
填充)但是相对于你可以通过使用for循环实现的加速来说相对较小,如果你忘记了.fill
你可以很困惑为什么你的数组神秘地是[empty x 5]
。您可以将上述内容封装为自定义函数,或者使用更有意的方法:
> Array.from(Array(5),(x,i)=>i)
[0, 1, 2, 3, 4]
你当然可以直接从那里进入你想做的任何事情,比如 python 的列表推导,例如[i**2 for i in range(5)]
:
> Array.from(Array(5), (_,i)=> i**2)
[0, 1, 4, 9, 16]
...或者如果您想变得更复杂...:
> Array.from(Array(5), (_,i)=>
const R = /*some computation*/;
return /*etc*/;
);
[2021 年 5 月编辑]:理论上,如今定义此类函数的最简单方法是 f=i=>i?[...f(i-1),i]:[]
,您可以将 f 替换为 range1
或任何名称,但这会非常慢(二次复杂度),因为中间结构,所以永远不应该使用。 f=i=>i?f(i-1)&&x.push(i)&&x:x=[]
是线性复杂性,但依赖于符号的滥用,并且不可读并且还会污染全局变量。但是,由于现在定义箭头函数(不绑定而是继承 this
)非常简洁,您可以包装上述解决方案:
const range1 = n=> Array.from(Array(n), (_,i)=> i+i);
// range1(5)==[1, 2, 3, 4, 5]
下面的一切都是历史:
经过一番思考,这是我能想到的 JavaScript 中标准 range(N)
函数的最短实现:
function range1(i)return i?range1(i-1).concat(i):[]
注意:不要在生产中使用它;它是 O(N^2)
与当前投票最多的答案对比:
function range1(i)var x=[];var i=1;while(x.push(i++)<i);return x
例子:
> range1(5)
[1, 2, 3, 4, 5]
这就像递归的典型代表,虽然我预计它会更长,直到我想到三元 if 语句,它将它减少到 42 个必要的字符。
请注意,返回 [start,end) 的“标准”range
函数可以通过 .concat(i-1)
编写。
更新:哦,我发现了一个非常短的版本,它通过滥用 for 循环、反向排序、赋值返回一个值的事实:for(y=[],i=20;y[--i]=i;)
仅包含 25 个字符(尽管你会想要 var y
您可以将其插入 for 循环,如果您不想要 0...19,则 +1)。如果你需要定义一个函数,它不会更短,如果你不需要创建一个函数,它比i?r(i-1).concat(i):[]
短。
添加了一些性能分析测试用例:似乎除了标准的有序 for 循环之外的所有东西都慢了 10 倍,至少在 V8 上是这样。 https://jsperf.com/array-range-in-javascript (当然,如果您以函数式编程并且无论如何都会使用函数调用来处理每个元素,那么这些都不重要。)
【讨论】:
非常好!要设置范围 1-20:function range(i) return i>1 ? range(i-1).concat(i-1) : [];
并使用 range(21)
;~)
真聪明!如果我在哪里 OP 我会选择这个答案。
哦,太棒了!非常巧妙地使用递归和concat()
developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
我应该提一下,虽然我的回答很简洁(如要求的那样),但它对于大范围可能效率不高,因为遗憾的是 javascript 的 .concat 可能不是 O(1) 操作。跨度>
第一个 ES6 替代方案可能会抛出 Supplied parameters do not match any signature of call target.
错误。这是因为 Array 原型中的fill()
方法必须接收填充值。查看我的解决方案以使用 fill()
method。【参考方案2】:
如果你对 0-20 没问题,以下是我最近打高尔夫球时的最新最爱:
[...'0'.repeat(21)].map((_,i)=>i)
Array.from(length:21,(_,i)=>i)
Array(21).fill().map((_,i)=>i)
[...Array(21)].map((_,i)=>i)
Array(21).map((_,i)=>i)
[...Array(21).keys()]
【讨论】:
【参考方案3】:如果您接受从 0 而不是 1 开始的计数器...
const zeroNineteen = [...Array(20).keys()];
// outputs [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
如果你真的需要从 1 开始:
const terserst = [...Array(21).keys()].slice(1);
它有 30 个字符,但还是可读的,你不觉得吗?
【讨论】:
【参考方案4】:while-- 是要走的路
var a=[],b=10;while(b--)a[b]=b+1
返回 [1,2,3,4,5,6,7,8,9,10]
用开始和长度解释
var array=[],length=20,start=5;while(length--)array[length]=length+start
返回 [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
想要范围?
用开始和结束来解释
var array=[],end=30,start=25,a=end-start+1;while(a--)array[a]=end--
返回 [25, 26, 27, 28, 29, 30]
为--
for(var a=[],b=20;b>0;b--,a[b]=b+1)
对于++
for(var a=[],b=0;b<20;b++,a[b]=b+1)
为什么要走这条路?
while -- 是最快的循环;
直接设置比push & concat快;
[] 也比 new Array(10) 快;
它的代码并不比其他所有代码长多少
字节节省技术:
-
将参数用作函数变量的占位符
如果不需要,不要使用 new Array(),push(),concat()
仅在需要时放置“();”。
在短函数中使用 a,b,c,d...。
所以如果你想要这个功能
有开始,结束(范围)
function range(a,b,c,d)d=[];c=b-a+1;while(c--)d[c]=b--;return d
所以现在 range(3,7) 返回 [3,4,5,6,7]
你在这里以多种方式保存字节,并且这个函数也非常快,因为它不使用concat,push,new Array并且它是用一段时间制作的--
【讨论】:
【参考方案5】:使用 ES6
numArr = Array(5).fill(0).reduce(arr=> arr.push(arr.length); return arr ,[])
【讨论】:
短一点:Array( 5 ).fill().reduce( arr => ( arr.push( arr.length ), arr ), [] )
【参考方案6】:
它可以通过 ES6 的功能来完成,目前只有 Firefox 支持。我在这里找到了一个兼容性表:http://kangax.github.io/compat-table/es6/
Array.from(new Array(20), (x,i) => i+1)
如果你想有一些其他的范围,那么我想你可以这样做
Array.from(new Array(5), (x,i) => i+5)
然后是 [5,6,7,8,9]
【讨论】:
这适用于 Chrome v45,如果您使用 Babel 转译 ES6,则可以使用。你也可以Array.from( length: 20 , (v, k) => k + 1);
【参考方案7】:
您可以使用 while 循环执行此操作,其中 push 发生在 condition.Array.push 返回数组的长度,这恰好与本例中的值相同。因此,您可以执行以下操作:
x = []; //normally would use var here
i = 1; //normally would use var here
while(x.push(i++)<20)
//at this point, x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
精简版(31 个字符)
x=[];i=1;while(x.push(i++)<20);
jsFiddle example
【讨论】:
哦!我喜欢。虽然很反常。我的理解是.push()
返回数组的长度。在 Mozilla Docs 中:developer.mozilla.org/en/JavaScript/Reference/Global_Objects/… “push 方法可用于轻松地将值附加到数组。此方法的返回值是调用该方法的对象的新长度属性。”碰巧在以 1 开头的数组中,最后一个 push()
ed 将是长度。哈!
@EndangeredMassa,x.Push() 返回新长度而不是值。
@EndangeredMassa。 x.push(i++) 是否等于 x 中元素的个数?
啊,是的。在这种特定情况下,它们是相同的。
他不使用var是为了节省空间,但是如果你实现了这个,请使用var,否则维护你的代码的人会找到你...【参考方案8】:
我会扩展 Array 的原型以使其易于访问:
Array.prototype.range = function(start, end)
if (!this.length)
while (end >= start)
this.push(start++);
else
throw "You can only call 'range' on an empty array";
return this;
;
var array = [].range(1, 20);
虽然就您要查找的语法糖而言,以上是我能想到的最接近的,但您可能想试试CoffeeScript。
它支持你所追求的符号。
CoffeeScript:
test = [1..20]
alert test
呈现为 JavaScript:
var test;
test = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
alert(test);
您可以在他们的网站上试用实时示例,并在您输入时查看它所做的转换。
只需单击顶部的 TRY COFFEESCRIPT 链接,您将获得一个控制台,您可以在其中测试一些代码。
【讨论】:
一切都很好,直到你的 js 需要与一些也喜欢扩展内置对象的第三方库合作...... 没有带来新的算法,但允许有趣和简洁的用法。我可以用那个。 @rob:如果一个人使用图书馆,他们应该确切地知道它的作用。我当然不会因为可能与库发生冲突而放弃扩展对象的做法。如果有冲突,您只需解决它。没什么大不了。至少它不应该是一个能胜任一半的程序员。 @artlung:是的,这是一个如此简单的过程,我不认为你会发现任何在算法上太令人兴奋的东西。我个人喜欢扩展原生类的原型(Object 除外)。这是该语言的一个很棒的功能,所以你不妨喜欢它。 :o) @artlung:你检查过CoffeeScript吗?我不是很喜欢它,但有些人喜欢它。这都是关于语法糖的。而且它似乎支持that 1..20 type of range notation。【参考方案9】:如果您希望在不考虑可读性的情况下无论如何都可以刮掉字符,这是我能做的最好的:
var x=[],i=0
while(i<20)
x[i]=i+++1
虽然比你的好不了多少。
编辑:
实际上这样效果更好,并且可以减少几个字符:
var x=[],i=0
while(i<20)
x[i]=++i
编辑 2:
这是我用最少字符输入的一般“范围”函数的条目:
function range(s,e)var x=[];while(s<e+1)x.push(s++);return x
同样,不要这样写代码。 :)
【讨论】:
i+++1
应该做什么?你的分号在哪里?这是 JavaScript 吗?
该构造使用++
运算符,并在其中添加1 +1
。不符合 Crockford 标准,但聪明而简洁。
嘿,它运行并产生正确的结果。不,我不会这样写代码!分号是可选的(但我总是使用它们),并且 i+++1 与 (i++) + 1 相同
你为什么要使用 i+++1 而不是 i+=2,这伤害了我的眼睛。
@Robert: i+=2 不是一回事,但在这种情况下你实际上可以使用 ++i 并且它可以工作。请注意,它在一般情况下不起作用,只是因为数组索引恰好比值小 1。【参考方案10】:
你总是可以创建一个函数...
function createNumArray(a, b)
var arr = [],
i = a;
while((arr[arr.length] = i) < b) i++
return arr;
这使您可以稍后编写简洁的代码,例如...
var arr = createNumArray(1, 20);
【讨论】:
【参考方案11】:我想这是最短的方法:
var i=0, arr = [];
while (i++<20)
arr.push(i);
或关联EndangeredMassa 的答案中的“反常”代码:
var i,arr; while (i=i||1, (arr=arr||[]).push(i++)<20)
【讨论】:
【参考方案12】:var i = 0;
var x = [];
while (i++ < 20) x.push(i);
JSFiddle
【讨论】:
虽然这段代码 sn-p 可以解决问题,但代码外的including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!【参考方案13】:我想不出字符少于 ~46 个的方法:
var a=[];while(a.length<20)a.push(a.length+1);
当然,你可以用它来做一个函数。
阅读有关函数的 cmets,您可以执行类似的操作
var range = function (start, end)
var arr = [];
while (start <= end)
arr.push(start++)
return arr;
;
然后range(1, 20)
将按预期返回数组。
【讨论】:
我不想复制 range() - 例如 Underscore.js 的方式:documentcloud.github.com/underscore/#range --var x = _.range(1, 20);
-- 问题更多的是关于底层方法和控制结构创建数组。我很好奇是否有我不知道的。
@artlung:不,你几乎得到了所有这些。循环或创建自己的方法,本质上是一个循环。【参考方案14】:
据我所知,您提到的使用 for 循环的选项是最简单的。
也就是说,
var x = [];
for (var i=1;i<=20;i++)
x.push(i);
【讨论】:
以上是关于在 JavaScript 中从 1..20 创建整数数组的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章