ฉันกำลังมองหาทางเลือกด้านล่างเพื่อสร้างอาร์เรย์ JavaScript ที่มี 1 ถึง N โดยที่ N รู้จักเฉพาะในรันไทม์
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
สำหรับฉันมันรู้สึกว่าควรมีวิธีการทำเช่นนี้โดยไม่ต้องวน
1 ... N
หรือไม่
ฉันกำลังมองหาทางเลือกด้านล่างเพื่อสร้างอาร์เรย์ JavaScript ที่มี 1 ถึง N โดยที่ N รู้จักเฉพาะในรันไทม์
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
สำหรับฉันมันรู้สึกว่าควรมีวิธีการทำเช่นนี้โดยไม่ต้องวน
1 ... N
หรือไม่
คำตอบ:
หากฉันได้สิ่งที่คุณต้องการคุณต้องการอาร์เรย์ของตัวเลข1..n
ที่คุณสามารถวนซ้ำในภายหลัง
หากนี่คือทั้งหมดที่คุณต้องการคุณสามารถทำสิ่งนี้แทนได้หรือไม่?
var foo = new Array(45); // create an empty array with length 45
จากนั้นเมื่อคุณต้องการใช้ ... (ยกเลิกการปรับให้เหมาะสมเช่น)
for(var i = 0; i < foo.length; i++){
document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>');
}
เช่นถ้าคุณไม่ต้องการเก็บอะไรในอาเรย์คุณแค่ต้องการภาชนะที่มีความยาวที่เหมาะสมซึ่งคุณสามารถทำซ้ำได้ ... นี่อาจจะง่ายกว่า
ดูการทำงานได้ที่นี่: http://jsfiddle.net/3kcvm/
var n = 45;
แล้ววนลูปจาก1..n
จะทำ
foo.length = M
--- ข้อมูลที่ถูกตัดออกไปจะหายไป ดูการทำงาน ==> jsfiddle.net/ACMXp
var n = 45;
ในความคิดเห็นไม่กี่ข้างต้นตั้งแต่ที่เขาจะได้ทำเพียงแค่
new Array(45);
จะไม่ "สร้างอาร์เรย์องค์ประกอบ 45" (ในความหมายเดียวกับที่[undefined,undefined,..undefined]
ทำ) มันค่อนข้างจะ "สร้างอาร์เรย์ที่ว่างเปล่าที่มีความยาว = 45" ( [undefined x 45]
) var foo = []; foo.length=45;
เช่นเดียวกับ นั่นเป็นเหตุผลforEach
และmap
จะไม่ใช้ในกรณีนี้
ใน ES6 ใช้อาร์เรย์จาก ()และคีย์ ()วิธีการ
Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
รุ่นที่สั้นกว่าโดยใช้ตัวดำเนินการสเปรด
[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
map
ไปยังอาร์เรย์เพื่อปรับค่า ( [...Array(10).keys()].map(x => x++);
) เพื่อเริ่มต้นที่ 1
map(x => x++)
ไปmap(x => ++x)
เนื่องจากมีความสำคัญเพิ่มขึ้นเกิดขึ้นหลังจากที่ผลตอบแทนค่า :)
map
เมื่อคุณสามารถslice
? [...Array(N+1).keys()].slice(1)
keys
และมีเพียง 1 แผนที่ ->Array.from(Array(10)).map((e,i)=>i+1)
from
Array.from(Array(10), (e,i)=>i+1)
คุณสามารถทำได้:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
ผล: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
หรือด้วยค่าสุ่ม:
Array.apply(null, {length: N}).map(Function.call, Math.random)
ผล: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.837758846580822, 0.857754289759, 0.85867485427864759, 0.85867485427,986,986,986,475,475,475,475,436,475 ผลลัพธ์
ก่อนอื่นให้สังเกตว่าNumber.call(undefined, N)
เทียบเท่ากับNumber(N)
ซึ่งเพิ่งกลับN
มา เราจะใช้ความจริงนั้นในภายหลัง
Array.apply(null, [undefined, undefined, undefined])
เทียบเท่ากับArray(undefined, undefined, undefined)
ซึ่งสร้างอาร์เรย์สามองค์ประกอบและกำหนดให้undefined
กับแต่ละองค์ประกอบ
คุณจะพูดถึงองค์ประกอบของN ได้อย่างไร? พิจารณาวิธีการArray()
ทำงานซึ่งไปบางอย่างเช่นนี้:
function Array() {
if ( arguments.length == 1 &&
'number' === typeof arguments[0] &&
arguments[0] >= 0 && arguments &&
arguments[0] < 1 << 32 ) {
return [ … ]; // array of length arguments[0], generated by native code
}
var a = [];
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
return a;
}
ตั้งแต่ ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)
ยังยอมรับวัตถุอาร์เรย์เหมือนเป็ดพิมพ์เป็นพารามิเตอร์ที่สอง ถ้าเราเรียกใช้Array.apply(null, { length: N })
แล้วมันจะดำเนินการ
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
ตอนนี้เรามีNundefined
อาร์เรย์องค์ประกอบที่มีองค์ประกอบของแต่ละชุดจะ เมื่อเราเรียกมันแต่ละองค์ประกอบจะถูกตั้งเป็นผลมาจากการ.map(callback, thisArg)
callback.call(thisArg, element, index, array)
ดังนั้น[undefined, undefined, …, undefined].map(Number.call, Number)
จะแมปองค์ประกอบแต่ละรายการ(Number.call).call(Number, undefined, index, array)
ซึ่งเหมือนกับNumber.call(undefined, index, array)
ที่เราสังเกตไว้ก่อนหน้านี้ซึ่งประเมินindex
ว่า ทำให้อาร์เรย์ที่มีองค์ประกอบเหมือนกับดัชนีเสร็จสมบูรณ์
ทำไมต้องเผชิญกับปัญหาArray.apply(null, {length: N})
แทนที่จะเป็นเพียงแค่Array(N)
? ท้ายที่สุดนิพจน์ทั้งสองจะส่งผลให้มีอาร์เรย์N -element ขององค์ประกอบที่ไม่ได้กำหนด ความแตกต่างคือในนิพจน์ก่อนหน้าแต่ละองค์ประกอบจะถูกตั้งค่าเป็นไม่ได้กำหนดอย่างชัดเจนในขณะที่องค์ประกอบหลังแต่ละองค์ประกอบไม่เคยถูกตั้งค่า ตามเอกสารของ.map()
:
callback
ถูกเรียกเฉพาะสำหรับดัชนีของอาร์เรย์ที่มีค่าที่ได้รับมอบหมาย; มันไม่ได้ถูกเรียกใช้สำหรับดัชนีที่ถูกลบไปหรือที่ไม่เคยมีการกำหนดค่า
ดังนั้นจึงArray(N)
ไม่เพียงพอ Array(N).map(Number.call, Number)
จะส่งผลให้อาร์เรย์เตรียมความยาวN
เนื่องจากเทคนิคนี้ขึ้นอยู่กับพฤติกรรมที่Function.prototype.apply()
ระบุใน ECMAScript 5 มันจะไม่ทำงานในเบราว์เซอร์ pre-ECMAScript 5 เช่น Chrome 14 และ Internet Explorer 9
Function.prototype.call
พารามิเตอร์แรกคือthis
วัตถุที่จะจับคู่โดยตรงกับArray.prototype.map
พารามิเตอร์ตัววนซ้ำของมันมีความหมายบางอย่าง
map
ค่านิยมที่ไม่ได้กำหนดในความคิดของฉัน อีกรุ่น (และอาจชัดเจนกว่าเล็กน้อยอีกต่อไปแม้ว่าจะนานกว่า) คือ: Array.apply(null, { length: N }).map(function(element, index) { return index; })
Array.apply(null, new Array(N)).map(function(_,i) { return i; })
หรือในกรณีของฟังก์ชั่น es6 และลูกศรยิ่งสั้นลง: Array.apply(null, new Array(N)).map((_,i) => i)
...
) และปุ่ม[ ...Array(N).keys() ].map( i => i+1);
Array(N).fill().map((_, i) => i+1);
Array.from(Array(N), (_, i) => i+1)
{ length: N }
แฮ็คArray.from({ length: N }, (_, i) => i+1)
ทุกรูปแบบข้างต้นอาร์เรย์สามารถผลิต initialised เป็นค่าที่ต้องการสวยมาก ๆ โดยการเปลี่ยนi+1
การแสดงออกที่ต้องการ (เช่นi*2
, -i
, 1+i*2
, i%2
และอื่น ๆ ) หากการแสดงออกสามารถแสดงออกโดยฟังก์ชั่นบางอย่างf
แล้วรูปแบบแรกกลายเป็นเพียง
[ ...Array(N).keys() ].map(f)
Array.from({length: 5}, (v, k) => k+1);
// [1,2,3,4,5]
เนื่องจากอาร์เรย์ถูกเตรียมใช้งานด้วยundefined
ในแต่ละตำแหน่งค่าของv
จะเป็นundefined
f
เช่น[ ...Array(N).keys() ].map((i) => f(i))
หรือง่ายกว่า
[ ...Array(N).keys() ].map(f)
k++
++k
อาร์เรย์จัดการความยาวโดยกำเนิด ดัชนีจะถูกเก็บไว้ในหน่วยความจำและอ้างอิง ณ จุดนั้น หากจำเป็นต้องทราบดัชนีแบบสุ่มindexOf
คุณสามารถใช้วิธีนั้นได้
สิ่งนี้กล่าวว่าสำหรับความต้องการของคุณคุณอาจต้องการประกาศอาร์เรย์ที่มีขนาดที่แน่นอน:
var foo = new Array(N); // where N is a positive integer
/* this will create an array of size, N, primarily for memory allocation,
but does not create any defined values
foo.length // size of Array
foo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array
*/
การใช้ประโยชน์จากตัวดำเนินการสเปรด ( ...
) และkeys
วิธีการช่วยให้คุณสร้างอาร์เรย์ชั่วคราวขนาด N เพื่อสร้างดัชนีแล้วอาร์เรย์ใหม่ที่สามารถกำหนดให้กับตัวแปรของคุณ:
var foo = [ ...Array(N).keys() ];
คุณสามารถสร้างขนาดของอาร์เรย์ที่คุณต้องการก่อนเติมด้วย undefined แล้วสร้าง array ใหม่โดยใช้map
ซึ่งจะตั้งค่าแต่ละองค์ประกอบเป็นดัชนี
var foo = Array(N).fill().map((v,i)=>i);
สิ่งนี้ควรเริ่มต้นกับความยาวของขนาด N และใส่ข้อมูลอาเรย์ในครั้งเดียว
Array.from({ length: N }, (v, i) => i)
แทนความคิดเห็นและความสับสนหากคุณต้องการเก็บค่าจาก 1..N ในตัวอย่างด้านบนมีตัวเลือกสองอย่าง:
++i
) ในกรณีที่ไม่ได้ใช้ดัชนี - และอาจเป็นวิธีที่มีประสิทธิภาพมากขึ้น - คือการสร้างอาร์เรย์ของคุณ แต่ทำให้ N แทน N + 1 จากนั้นเลื่อนไปด้านหน้า
ดังนั้นหากคุณต้องการ 100 หมายเลข:
let arr; (arr=[ ...Array(101).keys() ]).shift()
ใน ES6 คุณสามารถทำได้:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
แก้ไข: เปลี่ยนArray(45)
เป็นArray(N)
เนื่องจากคุณได้อัปเดตคำถามแล้ว
console.log(
Array(45).fill(0).map((e,i)=>i+1)
);
.join.split
รุ่นที่น่ารังเกียจ- แต่ฉันก็ยังคิดว่าลูปต่ำต้อยดีกว่า
map
อีกไม่นานจะกลายเป็นมาตรฐานสำหรับสิ่งต่าง ๆ เช่นนี้
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
.fill()
มีความจำเป็น ฉันเห็นว่ามันเป็นเมื่อฉันทดสอบกับการจำลองของโหนด แต่เนื่องจากArray(1)[0] === undefined
การเรียกเพื่อเติม () มีความแตกต่างกันArray(1).fill(undefined)
อย่างไร
ใช้วิธี Underscore _.range ที่นิยมมาก
// _.range([start], stop, [step])
_.range(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5); // => [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1); // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0); // => []
function range(start, end) {
var foo = [];
for (var i = start; i <= end; i++) {
foo.push(i);
}
return foo;
}
จากนั้นโทรมาโดย
var foo = range(1, 5);
ไม่มีวิธีการทำเช่นนี้ใน Javascript แต่เป็นฟังก์ชันยูทิลิตี้ที่ถูกต้องสมบูรณ์ในการสร้างหากคุณต้องการทำมากกว่าหนึ่งครั้ง
แก้ไข: ในความคิดของฉันต่อไปนี้เป็นฟังก์ชั่นช่วงที่ดีกว่า อาจเป็นเพราะฉันลำเอียงโดย LINQ แต่ฉันคิดว่ามันมีประโยชน์มากกว่าในหลายกรณี ไมล์สะสมของคุณอาจแตกต่างกันไป
function range(start, count) {
if(arguments.length == 1) {
count = start;
start = 0;
}
var foo = [];
for (var i = 0; i < count; i++) {
foo.push(start + i);
}
return foo;
}
Array
แทนArray.prototype
เพราะไม่มีเหตุผล (มันอาจจะถือว่าค่อนข้างโง่) ที่จะมีวิธีนี้ในทุก ๆ อาร์เรย์
Array.range(1, 5)
อาจจะมีความเหมาะสมมากขึ้น [].range(1, 5)
แต่มีบางสิ่งบางชนิดของเย็นเกี่ยวกับการเขียน
foo = [1, 2, 3]; bar = foo.range(0, 10);
ได้ แต่นั่นเป็นเพียง ... สับสน bar = Array.range(0, 10)
มีความชัดเจนและชัดเจนมากขึ้น ช่วงไม่มีอะไรเกี่ยวข้องกับอินสแตนซ์ดังนั้นจึงไม่มีเหตุผลที่จะทำให้เป็นวิธีการแบบอินสแตนซ์
วิธีที่เร็วที่สุดในการกรอกข้อมูลArray
ใน v8 คือ:
[...Array(5)].map((_,i) => i);
ผลลัพธ์จะเป็น: [0, 1, 2, 3, 4]
คำถามนี้มีคำตอบที่ซับซ้อนมากมาย แต่เป็นแบบง่าย ๆ :
[...Array(255).keys()].map(x => x + 1)
นอกจากนี้แม้ว่าข้างต้นจะสั้น (และเรียบร้อย) ในการเขียนฉันคิดว่าต่อไปนี้จะเร็วขึ้นเล็กน้อย (สำหรับความยาวสูงสุด:
127, Int8,
255, Uint8,
32,767, Int16,
65,535, Uint16,
2,147,483,647, Int32,
4,294,967,295, Uint32
(ขึ้นอยู่กับค่าจำนวนเต็มสูงสุด ) และยังมีเพิ่มเติมในอาร์เรย์ที่พิมพ์ด้วย ):
(new Uint8Array(255)).map(($,i) => i + 1);
แม้ว่าวิธีนี้จะไม่เหมาะอย่างยิ่งเพราะมันสร้างสองอาร์เรย์และใช้การประกาศตัวแปรพิเศษ "$" (ไม่แน่ใจว่าจะหลีกเลี่ยงวิธีใดในการใช้วิธีนี้) ฉันคิดว่าวิธีแก้ปัญหาต่อไปนี้เป็นวิธีที่เร็วที่สุดที่จะทำได้:
for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;
คุณสามารถใช้ตัวแปร "arr" ในขอบเขตปัจจุบันได้โดยง่าย
หากคุณต้องการสร้างฟังก์ชั่นที่เรียบง่ายจากฟังก์ชั่นนี้ (ด้วยการยืนยันขั้นพื้นฐาน):
function range(min, max) {
min = min && min.constructor == Number ? min : 0;
!(max && max.constructor == Number && max > min) && // boolean statements can also be used with void return types, like a one-line if statement.
((max = min) & (min = 0)); //if there is a "max" argument specified, then first check if its a number and if its graeter than min: if so, stay the same; if not, then consider it as if there is no "max" in the first place, and "max" becomes "min" (and min becomes 0 by default)
for(var i = 0, arr = new (
max < 128 ? Int8Array :
max < 256 ? Uint8Array :
max < 32768 ? Int16Array :
max < 65536 ? Uint16Array :
max < 2147483648 ? Int32Array :
max < 4294967296 ? Uint32Array :
Array
)(max - min); i < arr.length; i++) arr[i] = i + min;
return arr;
}
//and you can loop through it easily using array methods if you want
range(1,11).forEach(x => console.log(x));
//or if you're used to pythons `for...in` you can do a similar thing with `for...of` if you want the individual values:
for(i of range(2020,2025)) console.log(i);
//or if you really want to use `for..in`, you can, but then you will only be accessing the keys:
for(k in range(25,30)) console.log(k);
console.log(
range(1,128).constructor.name,
range(200).constructor.name,
range(400,900).constructor.name,
range(33333).constructor.name,
range(823, 100000).constructor.name,
range(10,4) // when the "min" argument is greater than the "max", then it just considers it as if there is no "max", and the new max becomes "min", and "min" becomes 0, as if "max" was never even written
);
ดังนั้นด้วยฟังก์ชั่นดังกล่าวข้างต้นช้าสุด "ง่ายหนึ่งซับ" กลายเป็นซุปเปอร์เร็วแม้สั้น:
range(1,14000);
fill
วิธีการใหม่:Array(255).fill(0,0,255)
คุณสามารถใช้สิ่งนี้:
new Array(/*any number which you want*/)
.join().split(',')
.map(function(item, index){ return ++index;})
ตัวอย่างเช่น
new Array(10)
.join().split(',')
.map(function(item, index){ return ++index;})
จะสร้างอาร์เรย์ต่อไปนี้:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
new Array(10).join().split(',').map(function() {return ++arguments[1]});
?
join
, ครั้งต่อไปsplit
, และอีกครั้งสำหรับสิ่งที่คุณต้องการทำจริง ๆ ) ไม่ดีเลย - ฉันรู้ว่าพวกเขาดูเหมือนจะตกหล่น ด้วยเหตุผลบางอย่าง แต่มันจะดีกว่าถ้าจะใช้วงแบบเก่าที่ดี!
ES6 นี้จะทำเคล็ดลับ:
[...Array(12).keys()]
ตรวจสอบผล:
[...Array(12).keys()].map(number => console.log(number))
[...Array(N + 1).keys()].slice(1)
จะให้ผล 1..N
[...Array(N + 1).keys()]
รหัสนี้ส่งกลับอาร์เรย์ที่ว่างเปล่า แต่เพียงในโหมดการผลิตโดยใช้งานโหมดการพัฒนา
.keys()
คำตอบที่ได้รับแล้วปีที่ผ่านมาและมี 500 + upvotes คำตอบของคุณเพิ่มไปยังอะไร?
หากคุณบังเอิญใช้d3.jsในแอปของคุณอย่างที่ฉันเป็น D3 จะมีฟังก์ชั่นช่วยเหลือที่ใช้สำหรับคุณ
ดังนั้นในการรับอาร์เรย์จาก 0 ถึง 4 มันง่ายเหมือน:
d3.range(5)
[0, 1, 2, 3, 4]
และรับอาร์เรย์ตั้งแต่ 1 ถึง 5 ตามที่คุณร้องขอ:
d3.range(1, 5+1)
[1, 2, 3, 4, 5]
ลองดูบทช่วยสอนนี้สำหรับข้อมูลเพิ่มเติม
การใช้ตัวดำเนินการกระจาย ES2015 / ES6
[...Array(10)].map((_, i) => i + 1)
console.log([...Array(10)].map((_, i) => i + 1))
i + 1
++i
จะทำให้ความรู้สึกมากกว่า
นี่อาจเป็นวิธีที่เร็วที่สุดในการสร้างอาร์เรย์ของตัวเลข
ที่สั้นที่สุด
var a=[],b=N;while(b--)a[b]=b+1;
inline
var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]
หากคุณต้องการเริ่มต้นจาก 1
var arr=(function(a,b){while(a--)b[a]=a+1;return b})(10,[]);
//arr=[1,2,3,4,5,6,7,8,9,10]
ต้องการฟังก์ชั่นหรือไม่?
function range(a,b,c){c=[];while(a--)c[a]=a+b;return c}; //length,start,placeholder
var arr=range(10,5);
//arr=[5,6,7,8,9,10,11,12,13,14]
ทำไม?
while
เป็นวงที่เร็วที่สุด
การตั้งค่าโดยตรงเร็วกว่า push
[]
เร็วกว่า new Array(10)
มันสั้น ... ดูรหัสแรก จากนั้นดูฟังก์ชั่นอื่น ๆ ทั้งหมดที่นี่
หากคุณต้องการไม่สามารถมีชีวิตอยู่ได้โดยไม่ต้องสำหรับ
for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]
หรือ
for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
console.time()
ที่จะได้รับสัญชาติญาณ แต่สำหรับหลักฐานที่คุณจะต้อง jsperf.com และมันแสดงให้เห็นคุณข้ามเบราว์เซอร์ผลจากคนอื่น ๆ (ฮาร์ดแวร์ที่แตกต่างกัน ฯลฯ )
var a=[],b=N;while(b--){a[b]=a+1};
วิธีใหม่ในการเติมArray
คือ:
const array = [...Array(5).keys()]
console.log(array)
ผลลัพธ์จะเป็น: [0, 1, 2, 3, 4]
หากคุณใช้ lodash คุณสามารถใช้_.range :
_.range([start=0], end, [step=1])
สร้างอาร์เรย์ของตัวเลข (บวกและ / หรือลบ) ที่กำลังดำเนินการตั้งแต่เริ่มต้นจนถึง แต่ไม่รวมถึงสิ้นสุด ขั้นตอนที่ -1 จะถูกใช้หากระบุการเริ่มต้นเชิงลบโดยไม่มีการสิ้นสุดหรือขั้นตอน หากไม่ได้ระบุจุดสิ้นสุดจะตั้งค่าให้เริ่มต้นด้วยเริ่มจากนั้นตั้งค่าเป็น 0
ตัวอย่าง:
_.range(4);
// ➜ [0, 1, 2, 3]
_.range(-4);
// ➜ [0, -1, -2, -3]
_.range(1, 5);
// ➜ [1, 2, 3, 4]
_.range(0, 20, 5);
// ➜ [0, 5, 10, 15]
_.range(0, -4, -1);
// ➜ [0, -1, -2, -3]
_.range(1, 4, 0);
// ➜ [1, 1, 1]
_.range(0);
// ➜ []
ด้วย ES6 คุณสามารถทำได้:
// `n` is the size you want to initialize your array
// `null` is what the array will be filled with (can be any other value)
Array(n).fill(null)
map
และforEach
จะใช้งานได้
รายงานสรุปขั้นสุดท้าย .. Drrruummm Rolll -
นี่คือรหัสที่สั้นที่สุดในการสร้างอาร์เรย์ขนาด N (ที่นี่ 10) โดยไม่ต้องใช้ ES6 เวอร์ชันของCoccoด้านบนนั้นปิด แต่ไม่สั้นที่สุด
(function(n){for(a=[];n--;a[n]=n+1);return a})(10)
แต่ชนะไม่มีปัญหานี้กอล์ฟรหัส (การแข่งขันในการแก้ปัญหาที่เกิดขึ้นโดยเฉพาะอย่างยิ่งในไบต์น้อยที่สุดของ source code) คือนิโก้ Ruotsalainen ใช้อาร์เรย์สร้างและผู้ประกอบการ ES6 การแพร่กระจาย (ไวยากรณ์ส่วนใหญ่ของ ES6 เป็น typeScript ที่ถูกต้อง แต่การติดตามไม่ได้ดังนั้นควรพิจารณาในขณะที่ใช้)
[...Array(10).keys()]
a
นี้จะสร้างตัวแปรทั่วโลก การวนซ้ำควรเป็นfor(var a=[];n--;a[n]=n+1)
มีอีกวิธีหนึ่งใน ES6 โดยใช้Array.fromซึ่งใช้เวลา 2 ข้อโต้แย้งข้อแรกคือ arrayLike (ในกรณีนี้คืออ็อบเจกต์ที่มีlength
คุณสมบัติ) และอันที่สองคือฟังก์ชั่นการแมป (ในกรณีนี้เราจับคู่รายการกับดัชนี)
Array.from({length:10}, (v,i) => i)
นี่คือสั้นและสามารถใช้สำหรับลำดับอื่น ๆ เช่นสร้างเลขคู่
Array.from({length:10}, (v,i) => i*2)
นอกจากนี้ยังมีประสิทธิภาพที่ดีกว่าวิธีอื่น ๆ ส่วนใหญ่เพราะมันวนซ้ำเพียงครั้งเดียวผ่านอาร์เรย์ ตรวจสอบ snippit เพื่อเปรียบเทียบ
// open the dev console to see results
count = 100000
console.time("from object")
for (let i = 0; i<count; i++) {
range = Array.from({length:10}, (v,i) => i )
}
console.timeEnd("from object")
console.time("from keys")
for (let i =0; i<count; i++) {
range = Array.from(Array(10).keys())
}
console.timeEnd("from keys")
console.time("apply")
for (let i = 0; i<count; i++) {
range = Array.apply(null, { length: 10 }).map(function(element, index) { return index; })
}
console.timeEnd("apply")
Array.from({length:N}, (v,i) => i+1)
การใช้วิธี Array ใหม่และ=>
ฟังก์ชั่นไวยากรณ์จากมาตรฐาน ES6 (เฉพาะ Firefox ในขณะที่เขียน)
โดยการเติมหลุมด้วยundefined
:
Array(N).fill().map((_, i) => i + 1);
Array.from
เปลี่ยน "หลุม" undefined
ให้Array.map
ทำงานตามที่คาดไว้:
Array.from(Array(5)).map((_, i) => i + 1)
Array.from({length: N}, (v, k) => k)
นี้:
Array.prototype.map.call
เช่นการ NodeLists document.querySelectorAll
กลับมาจาก developer.mozilla.org/en/docs/Web/JavaScript/Reference/
Array.from
เปลี่ยนค่าเบาบางลง แต่Array(5)
จะเรียกว่าเป็นวัตถุข้อโต้แย้งซึ่งในทางกลับตีความค่าเบาบางเป็นค่าที่ไม่ได้กำหนด :)
Array(...Array(9)).map((_, i) => i);
console.log(Array(...Array(9)).map((_, i) => i))
[...Array(9)].map((_, i) => i)
for(var i,a=[i=0];i<10;a[i++]=i);
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ใน ES6:
Array.from({length: 1000}, (_, i) => i);
ES5:
Array.apply(0, {length: 1000}).map(function(x,i){return i});
อีกเพียงรุ่นES6
ด้วยการใช้Array.from
อาร์กิวเมนต์ตัวเลือกที่สอง:
Array.from (arrayLike [, mapFn [, thisArg]])
เราสามารถสร้างอาเรย์ที่มีหมายเลขจากArray(10)
ตำแหน่งว่าง:
Array.from(Array(10), (_, i) => i)
var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);
[...Array(11).keys()].slice(1)
เท่าช้ากว่า
ดูเหมือนว่ามีเพียงรสชาติเดียวที่ไม่ได้อยู่ในรายการคำตอบที่ค่อนข้างสมบูรณ์นี้คือหนึ่งในนั้นมีเครื่องกำเนิดไฟฟ้า เพื่อแก้ไขว่า:
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
ซึ่งสามารถใช้ดังนี้:
gen(4) // [0,1,2,3]
สิ่งที่ดีเกี่ยวกับเรื่องนี้คือคุณไม่เพียง แต่ต้องเพิ่ม ... เพื่อรับแรงบันดาลใจจากคำตอบที่ @ igor-shubin คุณสามารถสร้างอาร์เรย์ของ randoms ได้อย่างง่ายดายมาก:
const gen = N => [...(function*(){let i=0;
while(i++<N) yield Math.random()
})()]
และมากกว่าสิ่งที่มีราคาแพงในเชิงปฏิบัติเช่น:
const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
// [0,5,10,15,...]
คุณสามารถทำได้แทน:
const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]
คุณสามารถใช้การเติม Array และแผนที่ได้จาก Es6 เช่นเดียวกับบางคนที่แนะนำในคำตอบที่ให้ไว้สำหรับคำถามนี้ ด้านล่างเป็นตัวอย่างบางส่วน:
Example-One: Array(10).fill(0).map((e,i)=>i+1)
Result-One: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Example-Two: Array(100/10).fill(0).map((e,i)=>(i*10)+10)
Result-Two:[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
ฉันชอบสิ่งนี้เพราะฉันพบว่ามันตรงไปตรงมาและง่ายขึ้น
Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
ที่มา: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
ใช้ ES6
const generateArray = n => [...Array(n)].map((_, index) => index + 1);
Array.from(Array(n))
หากผู้ประกอบการแพร่กระจายไม่ได้รับการสนับสนุน
map
กับ MDN : "มันไม่ได้ถูกเรียกสำหรับองค์ประกอบที่หายไปของอาเรย์ (นั่นคือดัชนีที่ไม่เคยถูกตั้งค่าซึ่งมี ถูกลบไปแล้วหรือยังไม่เคยกำหนดค่า)
Object.keys(Array.apply(0, Array(3))).map(Number)
[0, 1, 2]
ผลตอบแทน คล้ายกับคำตอบที่ยอดเยี่ยมของ Igor Shubinแต่มีเล่ห์เหลี่ยมน้อยกว่าเล็กน้อย
Array(3) // [undefined × 3]
สร้างอาร์เรย์ที่มีความยาว n = 3 น่าเสียดายที่อาเรย์นี้แทบจะไร้ประโยชน์กับเราดังนั้นเราต้อง ...Array.apply(0,Array(3)) // [undefined, undefined, undefined]
ทำให้อาร์เรย์ iterable หมายเหตุ: เป็นโมฆะทั่วไปของอาร์กิวเมนต์แรกที่ใช้ แต่สั้นกว่า 0Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']
จากนั้นรับค่าคีย์ของอาเรย์ (ใช้งานได้เนื่องจากอาเรย์คืออาร์เรย์ของ typeof เป็นวัตถุที่มีดัชนีสำหรับคีย์Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]
และแมปกุญแจ, แปลงสตริงเป็นตัวเลข