How to select the middle of an array? - javascript

I thought I could use
$ [1,2,3,4,5].splice((this.length / 2), 1)[0]
but it gives me
$ 1
I tried
$ [1,2,3,4,5].splice(function() { return this[this.length / 2, 1]})
but it gives me
[ 1, 2, 3, 4, 5 ]
I'm looking for a solution that gives me an integer and for even arrays is the lower of the two, e.g.
[1,2,3,4] givees 2
[1,2,3,4,5] gives 3
[1,2,3,4,5,6] gives 3
[1,2,3,4,5,6,7] gives 4

The issue is with this reference. Try this:
console.log(getMiddle([1,2,3,4]));
console.log(getMiddle([1,2,3,4,5]));
console.log(getMiddle([1,2,3,4,5,6]));
console.log(getMiddle([1,2,3,4,5,6,7]));
function getMiddle(arr){
return arr.splice(Math.floor((arr.length-1) / 2), 1)[0]
}
However, As #jonrsharpe 's comment states, splicing a single-element array from an index to the same index plus one then getting the first value in the result creates a redundant array. A better way to get the middle element would be the following:
console.log(getMiddle([1,2,3,4]));
console.log(getMiddle([1,2,3,4,5]));
console.log(getMiddle([1,2,3,4,5,6]));
console.log(getMiddle([1,2,3,4,5,6,7]));
function getMiddle(arr){
return arr[Math.floor((arr.length - 1) / 2)];
}

You should use something like that.
var data, remaining, hold, result;
data = ["1","2","3","4","5","6","7","8", "9"];
remaining = data.length % 2;
hold = Math.floor(data.length / 2);
result = data[(remaining + hold - 1)];
document.write(result);

You could create a prototype for getting the middle element/s.
Array.prototype.middle = function () {
const
half = this.length >> 1,
offset = 1 - this.length % 2;
return this.slice(half - offset, half + 1);
};
console.log([1, 2, 3, 4, 5].middle()); // [3]
console.log([1, 2, 3, 4, 5, 6].middle()); // [3, 4]
console.log([1, 2, 3, 4].middle()); // [2, 3]
.as-console-wrapper { max-height: 100% !important; top: 0; }

You cannot use this as a parameter because this is supposed to be called inside functions, whereas splice accept as parameters integers. If you really want to use this you may use a prototype. Use Math.floor function since arrays indexes only accept integers, and Math.floor rounds up to the lowest integer (ex: Math.floor(2.5) === 2).
Array.prototype.getMiddle = function () {
return this[Math.floor(this.length/2)]
}
console.log([1,2,3,4,5].getMiddle()) // 3
The above function only works when the length of the array is an odd number, since arrays whose length is an even number do not have "middle" element.
If you want to check if the array has a middle
Array.prototype.getMiddle = function () {
return (this.length % 2) ? this[Math.floor(this.length/2)] : null
}
console.log([1,2,3,4,5].getMiddle()) // 3
console.log([1,2,4,5].getMiddle()) // null
Alternative solutions:
var arr = [1,2,3,4,5]
var middleEl = arr[Math.floor(arr.length/2)]
console.log(middleEl) // 3
If you want to use splice
var arr = [1,2,3,4,5]
var middleEl = arr.splice((arr.length / 2), 1)[0]
console.log(middleEl)
If you want a function
console.log(middleEl([1,2,3,4,5])) //3
console.log(middleEl([1,2,4,5])) //null
function middleEl (arr) {
return (arr.length % 2) ? arr[Math.floor(arr.length/2)] : null
}

let arr = [ 1, 2, 3, 4, 5 ]
let len = arr.length;
let mid = Math.floor(len / 2);
console.log(arr[mid]);
// or
console.log(arr.slice(mid, mid + 1));
or if you want the middle two, you can do mid + 2 using a var that tests to see if the length is even.

Why not simply, assuming a.length > 0:
const a = [1, 2, 3, 4, 5]
console.log(a[(a.length - 1) >> 1])
const b = [1, 2, 3, 4, 5, 6]
console.log(b[(b.length - 1) >> 1])
I think this should be a fairly fast way of doing it. The >> operator is an integer shift, which divides the number by two - ignoring decimals.

Related

Initialize array by range [duplicate]

I'm looking for any alternatives to the below for creating a JavaScript array containing 1 through to N where N is only known at runtime.
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
To me it feels like there should be a way of doing this without the loop.
In ES6 using Array from() and keys() methods.
Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Shorter version using spread operator.
[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Start from 1 by passing map function to Array from(), with an object with a length property:
Array.from({length: 10}, (_, i) => i + 1)
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
You can do so:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
or with random values:
Array.apply(null, {length: N}).map(Function.call, Math.random)
result: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765,
0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.5577575915958732, 0.16363654541783035]
Explanation
First, note that Number.call(undefined, N) is equivalent to Number(N), which just returns N. We'll use that fact later.
Array.apply(null, [undefined, undefined, undefined]) is equivalent to Array(undefined, undefined, undefined), which produces a three-element array and assigns undefined to each element.
How can you generalize that to N elements? Consider how Array() works, which goes something like this:
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;
}
Since ECMAScript 5, Function.prototype.apply(thisArg, argsArray) also accepts a duck-typed array-like object as its second parameter. If we invoke Array.apply(null, { length: N }), then it will execute
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
Now we have an N-element array, with each element set to undefined. When we call .map(callback, thisArg) on it, each element will be set to the result of callback.call(thisArg, element, index, array). Therefore, [undefined, undefined, …, undefined].map(Number.call, Number) would map each element to (Number.call).call(Number, undefined, index, array), which is the same as Number.call(undefined, index, array), which, as we observed earlier, evaluates to index. That completes the array whose elements are the same as their index.
Why go through the trouble of Array.apply(null, {length: N}) instead of just Array(N)? After all, both expressions would result an an N-element array of undefined elements. The difference is that in the former expression, each element is explicitly set to undefined, whereas in the latter, each element was never set. According to the documentation of .map():
callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
Therefore, Array(N) is insufficient; Array(N).map(Number.call, Number) would result in an uninitialized array of length N.
Compatibility
Since this technique relies on behaviour of Function.prototype.apply() specified in ECMAScript 5, it will not work in pre-ECMAScript 5 browsers such as Chrome 14 and Internet Explorer 9.
Multiple ways using ES6
Using spread operator (...) and keys method
[ ...Array(N).keys() ].map( i => i+1);
Fill/Map
Array(N).fill().map((_, i) => i+1);
Array.from
Array.from(Array(N), (_, i) => i+1)
Array.from and { length: N } hack
Array.from({ length: N }, (_, i) => i+1)
Note about generalised form
All the forms above can produce arrays initialised to pretty much any desired values by changing i+1 to expression required (e.g. i*2, -i, 1+i*2, i%2 and etc). If expression can be expressed by some function f then the first form becomes simply
[ ...Array(N).keys() ].map(f)
Examples:
Array.from({length: 5}, (v, k) => k+1);
// [1,2,3,4,5]
Since the array is initialized with undefined on each position, the value of v will be undefined
Example showcasing all the forms
let demo= (N) => {
console.log(
[ ...Array(N).keys() ].map(( i) => i+1),
Array(N).fill().map((_, i) => i+1) ,
Array.from(Array(N), (_, i) => i+1),
Array.from({ length: N }, (_, i) => i+1)
)
}
demo(5)
More generic example with custom initialiser function f i.e.
[ ...Array(N).keys() ].map((i) => f(i))
or even simpler
[ ...Array(N).keys() ].map(f)
let demo= (N,f) => {
console.log(
[ ...Array(N).keys() ].map(f),
Array(N).fill().map((_, i) => f(i)) ,
Array.from(Array(N), (_, i) => f(i)),
Array.from({ length: N }, (_, i) => f(i))
)
}
demo(5, i=>2*i+1)
If I get what you are after, you want an array of numbers 1..n that you can later loop through.
If this is all you need, can you do this instead?
var foo = new Array(45); // create an empty array with length 45
then when you want to use it... (un-optimized, just for example)
for(var i = 0; i < foo.length; i++){
document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>');
}
e.g. if you don't need to store anything in the array, you just need a container of the right length that you can iterate over... this might be easier.
See it in action here: http://jsfiddle.net/3kcvm/
Arrays innately manage their lengths. As they are traversed, their indexes can be held in memory and referenced at that point. If a random index needs to be known, the indexOf method can be used.
This said, for your needs you may just want to declare an array of a certain size:
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
*/
ES6
Spread
Making use of the spread operator (...) and keys method, enables you to create a temporary array of size N to produce the indexes, and then a new array that can be assigned to your variable:
var foo = [ ...Array(N).keys() ];
Fill/Map
You can first create the size of the array you need, fill it with undefined and then create a new array using map, which sets each element to the index.
var foo = Array(N).fill().map((v,i)=>i);
Array.from
This should be initializing to length of size N and populating the array in one pass.
Array.from({ length: N }, (v, i) => i)
In lieu of the comments and confusion, if you really wanted to capture the values from 1..N in the above examples, there are a couple options:
if the index is available, you can simply increment it by one (e.g., ++i).
in cases where index is not used -- and possibly a more efficient way -- is to create your array but make N represent N+1, then shift off the front.
So if you desire 100 numbers:
let arr; (arr=[ ...Array(101).keys() ]).shift()
In ES6 you can do:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
Edit:
Changed Array(45) to Array(N) since you've updated the question.
console.log(
Array(45).fill(0).map((e,i)=>i+1)
);
Use the very popular Underscore _.range method
// _.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;
}
Then called by
var foo = range(1, 5);
There is no built-in way to do this in Javascript, but it's a perfectly valid utility function to create if you need to do it more than once.
Edit: In my opinion, the following is a better range function. Maybe just because I'm biased by LINQ, but I think it's more useful in more cases. Your mileage may vary.
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;
}
the fastest way to fill an Array in v8 is:
[...Array(5)].map((_,i) => i);
result will be: [0, 1, 2, 3, 4]
Performance
Today 2020.12.11 I performed tests on macOS HighSierra 10.13.6 on Chrome v87, Safari v13.1.2 and Firefox v83 for chosen solutions.
Results
For all browsers
solution O (based on while) is the fastest (except Firefox for big N - but it's fast there)
solution T is fastest on Firefox for big N
solutions M,P is fast for small N
solution V (lodash) is fast for big N
solution W,X are slow for small N
solution F is slow
Details
I perform 2 tests cases:
for small N = 10 - you can run it HERE
for big N = 1000000 - you can run it HERE
Below snippet presents all tested solutions A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
function A(N) {
return Array.from({length: N}, (_, i) => i + 1)
}
function B(N) {
return Array(N).fill().map((_, i) => i+1);
}
function C(N) {
return Array(N).join().split(',').map((_, i) => i+1 );
}
function D(N) {
return Array.from(Array(N), (_, i) => i+1)
}
function E(N) {
return Array.from({ length: N }, (_, i) => i+1)
}
function F(N) {
return Array.from({length:N}, Number.call, i => i + 1)
}
function G(N) {
return (Array(N)+'').split(',').map((_,i)=> i+1)
}
function H(N) {
return [ ...Array(N).keys() ].map( i => i+1);
}
function I(N) {
return [...Array(N).keys()].map(x => x + 1);
}
function J(N) {
return [...Array(N+1).keys()].slice(1)
}
function K(N) {
return [...Array(N).keys()].map(x => ++x);
}
function L(N) {
let arr; (arr=[ ...Array(N+1).keys() ]).shift();
return arr;
}
function M(N) {
var arr = [];
var i = 0;
while (N--) arr.push(++i);
return arr;
}
function N(N) {
var a=[],b=N;while(b--)a[b]=b+1;
return a;
}
function O(N) {
var a=Array(N),b=0;
while(b<N) a[b++]=b;
return a;
}
function P(N) {
var foo = [];
for (var i = 1; i <= N; i++) foo.push(i);
return foo;
}
function Q(N) {
for(var a=[],b=N;b--;a[b]=b+1);
return a;
}
function R(N) {
for(var i,a=[i=0];i<N;a[i++]=i);
return a;
}
function S(N) {
let foo,x;
for(foo=[x=N]; x; foo[x-1]=x--);
return foo;
}
function T(N) {
return new Uint8Array(N).map((item, i) => i + 1);
}
function U(N) {
return '_'.repeat(5).split('').map((_, i) => i + 1);
}
function V(N) {
return _.range(1, N+1);
}
function W(N) {
return [...(function*(){let i=0;while(i<N)yield ++i})()]
}
function X(N) {
function sequence(max, step = 1) {
return {
[Symbol.iterator]: function* () {
for (let i = 1; i <= max; i += step) yield i
}
}
}
return [...sequence(N)];
}
[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X].forEach(f=> {
console.log(`${f.name} ${f(5)}`);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"> </script>
This snippet only presents functions used in performance tests - it does not perform tests itself!
And here are example results for chrome
This question has a lot of complicated answers, but a simple one-liner:
[...Array(255).keys()].map(x => x + 1)
Also, although the above is short (and neat) to write, I think the following is a bit faster
(for a max length of:
127, Int8,
255, Uint8,
32,767, Int16,
65,535, Uint16,
2,147,483,647, Int32,
4,294,967,295, Uint32.
(based on the max integer values), also here's more on Typed Arrays):
(new Uint8Array(255)).map(($,i) => i + 1);
Although this solution is also not so ideal, because it creates two arrays, and uses the extra variable declaration "$" (not sure any way to get around that using this method). I think the following solution is the absolute fastest possible way to do this:
for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;
Anytime after this statement is made, you can simple use the variable "arr" in the current scope;
If you want to make a simple function out of it (with some basic verification):
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
);
so, with the above function, the above super-slow "simple one-liner" becomes the super-fast, even-shorter:
range(1,14000);
Using ES2015/ES6 spread operator
[...Array(10)].map((_, i) => i + 1)
console.log([...Array(10)].map((_, i) => i + 1))
You can use this:
new Array(/*any number which you want*/)
.join().split(',')
.map(function(item, index){ return ++index;})
for example
new Array(10)
.join().split(',')
.map(function(item, index){ return ++index;})
will create following array:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
If you happen to be using d3.js in your app as I am, D3 provides a helper function that does this for you.
So to get an array from 0 to 4, it's as easy as:
d3.range(5)
[0, 1, 2, 3, 4]
and to get an array from 1 to 5, as you were requesting:
d3.range(1, 5+1)
[1, 2, 3, 4, 5]
Check out this tutorial for more info.
This is probably the fastest way to generate an array of numbers
Shortest
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]
If you want to start from 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]
Want a function?
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]
WHY?
while is the fastest loop
Direct setting is faster than push
[] is faster than new Array(10)
it's short... look the first code. then look at all other functions in here.
If you like can't live without for
for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]
or
for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
If you are using lodash, you can use _.range:
_.range([start=0], end, [step=1])
Creates an array of numbers
(positive and/or negative) progressing from start up to, but not
including, end. A step of -1 is used if a negative start is specified
without an end or step. If end is not specified, it's set to start
with start then set to 0.
Examples:
_.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);
// ➜ []
the new way to filling Array is:
const array = [...Array(5).keys()]
console.log(array)
result will be: [0, 1, 2, 3, 4]
with ES6 you can do:
// `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)
Very simple and easy to generate exactly 1 - N
const [, ...result] = Array(11).keys();
console.log('Result:', result);
Final Summary report .. Drrruummm Rolll -
This is the shortest code to generate an Array of size N (here 10) without using ES6. Cocco's version above is close but not the shortest.
(function(n){for(a=[];n--;a[n]=n+1);return a})(10)
But the undisputed winner of this Code golf(competition to solve a particular problem in the fewest bytes of source code) is Niko Ruotsalainen . Using Array Constructor and ES6 spread operator . (Most of the ES6 syntax is valid typeScript, but following is not. So be judicious while using it)
[...Array(10).keys()]
https://stackoverflow.com/a/49577331/8784402
With Delta
For javascript
smallest and one-liner
[...Array(N)].map((v, i) => from + i * step);
Examples and other alternatives
Array.from(Array(10).keys()).map(i => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
[...Array(10).keys()].map(i => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
Array(10).fill(0).map((v, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Array(10).fill().map((v, i) => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
[...Array(10)].map((v, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Range Function
const range = (from, to, step) =>
[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
range(0, 9, 2);
//=> [0, 2, 4, 6, 8]
// can also assign range function as static method in Array class (but not recommended )
Array.range = (from, to, step) =>
[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
Array.range(2, 10, 2);
//=> [2, 4, 6, 8, 10]
Array.range(0, 10, 1);
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Array.range(2, 10, -1);
//=> []
Array.range(3, 0, -1);
//=> [3, 2, 1, 0]
As Iterators
class Range {
constructor(total = 0, step = 1, from = 0) {
this[Symbol.iterator] = function* () {
for (let i = 0; i < total; yield from + i++ * step) {}
};
}
}
[...new Range(5)]; // Five Elements
//=> [0, 1, 2, 3, 4]
[...new Range(5, 2)]; // Five Elements With Step 2
//=> [0, 2, 4, 6, 8]
[...new Range(5, -2, 10)]; // Five Elements With Step -2 From 10
//=>[10, 8, 6, 4, 2]
[...new Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]
// Also works with for..of loop
for (i of new Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2
As Generators Only
const Range = function* (total = 0, step = 1, from = 0) {
for (let i = 0; i < total; yield from + i++ * step) {}
};
Array.from(Range(5, -2, -10));
//=> [-10, -12, -14, -16, -18]
[...Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]
// Also works with for..of loop
for (i of Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2
// Lazy loaded way
const number0toInf = Range(Infinity);
number0toInf.next().value;
//=> 0
number0toInf.next().value;
//=> 1
// ...
From-To with steps/delta
using iterators
class Range2 {
constructor(to = 0, step = 1, from = 0) {
this[Symbol.iterator] = function* () {
let i = 0,
length = Math.floor((to - from) / step) + 1;
while (i < length) yield from + i++ * step;
};
}
}
[...new Range2(5)]; // First 5 Whole Numbers
//=> [0, 1, 2, 3, 4, 5]
[...new Range2(5, 2)]; // From 0 to 5 with step 2
//=> [0, 2, 4]
[...new Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]
using Generators
const Range2 = function* (to = 0, step = 1, from = 0) {
let i = 0,
length = Math.floor((to - from) / step) + 1;
while (i < length) yield from + i++ * step;
};
[...Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]
let even4to10 = Range2(10, 2, 4);
even4to10.next().value;
//=> 4
even4to10.next().value;
//=> 6
even4to10.next().value;
//=> 8
even4to10.next().value;
//=> 10
even4to10.next().value;
//=> undefined
For Typescript
class _Array<T> extends Array<T> {
static range(from: number, to: number, step: number): number[] {
return Array.from(Array(Math.floor((to - from) / step) + 1)).map(
(v, k) => from + k * step
);
}
}
_Array.range(0, 9, 1);
Solution for empty array and with just number in array
const arrayOne = new Array(10);
console.log(arrayOne);
const arrayTwo = [...Array(10).keys()];
console.log(arrayTwo);
var arrayThree = Array.from(Array(10).keys());
console.log(arrayThree);
const arrayStartWithOne = Array.from(Array(10).keys(), item => item + 1);
console.log(arrayStartWithOne)
✅ Simply, this worked for me:
[...Array(5)].map(...)
There is another way in ES6, using Array.from which takes 2 arguments, the first is an arrayLike (in this case an object with length property), and the second is a mapping function (in this case we map the item to its index)
Array.from({length:10}, (v,i) => i)
this is shorter and can be used for other sequences like generating even numbers
Array.from({length:10}, (v,i) => i*2)
Also this has better performance than most other ways because it only loops once through the array.
Check the snippit for some comparisons
// 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")
Fast
This solution is probably fastest it is inspired by lodash _.range function (but my is simpler and faster)
let N=10, i=0, a=Array(N);
while(i<N) a[i++]=i;
console.log(a);
Performance advantages over current (2020.12.11) existing answers based on while/for
memory is allocated once at the beginning by a=Array(N)
increasing index i++ is used - which looks is about 30% faster than decreasing index i-- (probably because CPU cache memory faster in forward direction)
Speed tests with more than 20 other solutions was conducted in this answer
Using new Array methods and => function syntax from ES6 standard (only Firefox at the time of writing).
By filling holes with undefined:
Array(N).fill().map((_, i) => i + 1);
Array.from turns "holes" into undefined so Array.map works as expected:
Array.from(Array(5)).map((_, i) => i + 1)
In ES6:
Array.from({length: 1000}, (_, i) => i).slice(1);
or better yet (without the extra variable _ and without the extra slice call):
Array.from({length:1000}, Number.call, i => i + 1)
Or for slightly faster results, you can use Uint8Array, if your list is shorter than 256 results (or you can use the other Uint lists depending on how short the list is, like Uint16 for a max number of 65535, or Uint32 for a max of 4294967295 etc. Officially, these typed arrays were only added in ES6 though). For example:
Uint8Array.from({length:10}, Number.call, i => i + 1)
ES5:
Array.apply(0, {length: 1000}).map(function(){return arguments[1]+1});
Alternatively, in ES5, for the map function (like second parameter to the Array.from function in ES6 above), you can use Number.call
Array.apply(0,{length:1000}).map(Number.call,Number).slice(1)
Or, if you're against the .slice here also, you can do the ES5 equivalent of the above (from ES6), like:
Array.apply(0,{length:1000}).map(Number.call, Function("i","return i+1"))
Array(...Array(9)).map((_, i) => i);
console.log(Array(...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]
It seems the only flavor not currently in this rather complete list of answers is one featuring a generator; so to remedy that:
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
which can be used thus:
gen(4) // [0,1,2,3]
The nice thing about this is you don't just have to increment... To take inspiration from the answer #igor-shubin gave, you could create an array of randoms very easily:
const gen = N => [...(function*(){let i=0;
while(i++<N) yield Math.random()
})()]
And rather than something lengthy operationally expensive like:
const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
// [0,5,10,15,...]
you could instead do:
const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]

How to return half of an array short way?

so I answer this Q but I believe there is another way
the Q is :
Write a function halve that copies the first half of an array. With an odd number of array elements, the middle element should belong to the first half. halve([1, 2, 3, 4]) should return [1, 2].
and ([1, 2, 3, 4, 5]) return [ 1, 2, 3 ].
function halve(x) {
let len = x.length / 2 - 0.5
let xx = x[len]
if (x.length % 2 === 0) {
return x.slice(0, x.length / 2)
} else {
return x.slice(0, xx)
}
}
console.log(halve([1, 2, 3, 4]));
You can use built-in filter function
function halve(x){
return x.filter((i, idx) => idx < Math.floor(x.length / 2))
}
console.log( halve([1, 2, 3, 4]));
function halve(arr){
let half = arr.length / 2 + 0.5;
return arr.slice(0, half)
}
You can compute the length and use .filter() to find out whether the item is an early item, using the fact that the second parameter of .filter() is the index to your advantage.
function halve(x) {
let len = Math.ceil(x.length / 2);
return x.filter((item, index) => index < len);
}
console.log(halve([1, 2, 3, 4]));
console.log(halve([1, 2, 3, 4, 5]));
arr.slice(0, -arr.length / 2);

How to ignore left part and middle element of the array(if odd array) to check existence of element in the right part?

I am trying to return
true, if an item is within the second half of an array
false, if the item is within the first half
false, if it is the middle item of the odd array.
I have some working code to test this, however I am stuck at on making sure that the middle item of an odd array is not tested.
function isItemPastHalf(array, item) {
var halfWayThough = Math.floor(array.length / 2)
var arrayFirstHalf = array.slice(0, halfWayThough);
var arraySecondHalf = array.slice(halfWayThough, array.length);
return arraySecondHalf.includes(item);
}
var array = [1, 2, 3];
console.log(isItemPastHalf(array, 2));
So far this code will not work on array = [1, 2, 3] item = 2 as 2 is the middle of an odd which should return false. The other tests for this particular problem include even length arrays. Has anyone got any suggestions for what I can use?
Math.ceil() will do the trick here instead of Math.floor()
function isItemPastHalf(array, item) {
var halfWayThough = Math.ceil(array.length / 2);
var arrayFirstHalf = array.slice(0, halfWayThough);
var arraySecondHalf = array.slice(halfWayThough, array.length);
return arraySecondHalf.includes(item);
}
var array = [1, 2, 3, 4, 5, 6, 7];
console.log(isItemPastHalf(array, 3));
console.log(isItemPastHalf(array, 2));
console.log(isItemPastHalf(array, 4));
you might enhance the function by searching for the index first and then decide what to return as follows
function isItemPastHalf (array, item) {
let idx = array.lastIndexOf(item);
let middleIndex = Math.ceil(array.length/2)-1;
return idx > middleIndex;
}
You could use findIndex method of Array.
function isElementInTheSecondHalfOfTheArray(element, array) {
const index = array.findIndex(arrayElement => arrayElement === element);
return index > (array.length - 1) / 2;
}
console.log( isElementInTheSecondHalfOfTheArray(1, [1, 2, 3]) );
console.log( isElementInTheSecondHalfOfTheArray(2, [1, 2, 3]) );
console.log( isElementInTheSecondHalfOfTheArray(3, [1, 2, 3]) );
I'd suggest the following approach:
function isItemPastHalf(array, item) {
// we find the index of the item in the array (which returns -1
// if the item is not found) and check to see if that is greater
// than, or equal to, the floored length of the array when divided
// by 2; we use Math.floor() rather than Math.ceil() because
// JavaScript arrays are zero-indexed:
return array.indexOf(item) >= (Math.floor(array.length / 2));
}
var array = [1, 2, 3];
console.log(isItemPastHalf(array, 2));
[JS Fiddle demo](https://jsfiddle.net/davidThomas/cp6vLmsy/.
References:
Array.length.
Array.prototype.indexOf().
Math.ceil().
Math.floor().
let numbers = [1, 2, 3, 4, 5]
function isItemPastHalf(array, item){
if((array.indexOf(item)*2) > array.length)
return true;
return false
}
console.log(isItemPastHalf(numbers,3)) //false if it is the middle item
If the index of the item multiply by two is still smaller than the array length, the item must be on the first half.
function isItemPastHalf(array, item) {
let itemIndex = array.lastIndexOf(item)
let mid = Math.floor(array.length/2)
return mid < itemIndex;
}
var oddLengthArray = [1, 2, 3, 4, 5, 6, 7];
var evenLengthArray = [1, 2, 3, 4, 5, 6];
console.log("ODD LENGTH ARRAY")
console.log("3",isItemPastHalf(oddLengthArray, 3));
console.log("4",isItemPastHalf(oddLengthArray, 4));
console.log("5",isItemPastHalf(oddLengthArray, 5));
console.log("ODD LENGTH ARRAY")
console.log("3",isItemPastHalf(evenLengthArray, 3));
console.log("4",isItemPastHalf(evenLengthArray, 4));
console.log("5",isItemPastHalf(evenLengthArray, 5));

What's the most concise way in javascript to find consecutive dups in an array, sum them up and reiterate?

Example
I have an array of:
const myArr = [1, 1, 1, 3, 2, 2, 4, 3];
If I were pass it to the function it should produce the output like so:
//result: [2, 1, 3, 8, 3]
The consecutive first two 1s and 2s were consecutive duplicates so they were summed up.
The first two consecutive 1s became 2 so it now doesn't match.
The consecutive 2s became 4 so it matched the next running number and summed up again resulting in an 8
Although the 3s are duplicate they we're not summed up because they're not consecutive
Bonus
It would be great if someone can demonstrate this using javascript's array functions map or reduce.
Is this possible without any kind of recursion? someone mentioned its possible, then I'd be nice if it didn't use recursion
EDIT
Adding this here because some have already provided answers.
In the case of:
const myArr = [1, 1, 1, 1];
// result: [4]
const myArr = [1, 1, 1, 1, 3, 2, 2, 4, 3];
// result: [4, 3, 8, 3]
Another interesting case that didn't pass my mind:
const myArr = [1, 1, 2, 2];
//result [4, 2] instead of [2,4]
It should check against the new array as soon a change was made
With the assumption that this will be used only on arrays of numbers, this is simple enough to do with reduce.
function duplicateAddition(input) {
var last;
var result = input;
do {
last = result;
result = last.reduce(function (carry, item) {
if (carry[carry.length - 1] == item) {
carry[carry.length - 1] *= 2;
} else {
carry.push(item);
}
return carry;
}, []);
} while (last.length != result.length);
return result;
}
Assuming the array always contains numbers, the most concise I can think of would be
function merge(arr) {
var x = String(arr),
y = x.replace(/([^,]),\1/, (_,m)=>2*m);
return x.length == y.length ? y.split(",").map(Number) : merge(y);
}
If you want to avoid the tail recursion, it's trivial to convert that to a loop:
function merge(arr) {
var y = String(arr);
do {
var x = y;
y = x.replace(/([^,]),\1/, (_,m)=>2*m);
} while(x.length != y.length)
return y.split(",").map(Number);
}
or
function merge(arr) {
for (var x=String(arr), y=""; x.length!=y.length; x=y.replace(/([^,]),\1/, (_,m)=>2*m))
y=x;
return x.split(",").map(Number);
}
Btw, to alter the behaviour of the algorithm to get [2, 4] instead of [4, 2] from [1, 1, 2, 2] (i.e. find all duplicates and sum them before reiterating), you'd only need to add the /global flag to the regex.
This solution uses a recursive generator. It has the advantage that it pretty much says what it means and does what it says.
function* x([first, second, ...rest]) {
if (first !== undefined) {
if (first !== second) yield first; else second *= 2;
yield* x([second, ...x(rest)]);
}
}
function test(a) { console.log(Array.from(x(a))); }
test([1, 1, 1, 3, 2, 2, 4, 3]);
test([1, 1, 1, 1]);
test([1, 1, 2, 2]);
In this solution, the input [1, 1, 2, 2] produces [2, 4]. That is because the logic greedily collapses the 2, 2 into a 4, which then does not match the 2 resulting from 1, 1. If this behavior is not desired, then it might suffice to change the line above to:
yield* x([second, ...rest]);
This is a simple game of unshifting from array a to pushing array b. So if a[0] === a[1] you take the first two items from array a, get their sum and push it into array b but if a[0] !== a[1] then take only the first item and push it into array b. However before we push the interim value (t in below snippet) we check the last item of array b to see if it's equal to the interim. If they are equal we just double the last item of array b if not just push interim (t) over b.
Then make a tail call optimized recursive invoking.
function sumAndReduce(a, b = []){
var t = 0;
if (!a.length) return b;
t = a[0] === a[1] ? a.splice(0,2).reduce((p,c) => p+c)
: a.splice(0,1)[0];
b[b.length-1] === t ? b[b.length-1] += t
: b.push(t);
return sumAndReduce(a,b);
}
var myArr = [1, 1, 1, 3, 2, 2, 4, 3],
result = sumAndReduce(myArr);
console.log(JSON.stringify(result));
console.log(JSON.stringify(sumAndReduce([1, 1, 1, 1])));
console.log(JSON.stringify(sumAndReduce([1, 1, 2, 2])));
Well... if you don't want recursion even if it is a tail call optimized one, then it's very trivial to convert the above code into an iterative one with a while loop. I'll leave it to you..!
So i can not make sure if your request as per an input [1,1,2,2] breaks the initial conditions but here is a modified version of the above code to comply with that as well.
function sumAndReduce(a, b = []){
var t = 0;
if (!a.length) return b;
t = a[0] !== a[1] || b[b.length-1] === a[0] ? a.splice(0,1)[0]
: a.splice(0,2).reduce((p,c) => p+c);
b[b.length-1] === t ? b[b.length-1] += t
: b.push(t);
return sumAndReduce(a,b);
}
var myArr = [1, 1, 1, 3, 2, 2, 4, 3],
result = sumAndReduce(myArr);
console.log(JSON.stringify(result));
console.log(JSON.stringify(sumAndReduce([1, 1, 1, 1])));
console.log(JSON.stringify(sumAndReduce([1, 1, 2, 2])));

The right way to create an array with N range? [duplicate]

I'm looking for any alternatives to the below for creating a JavaScript array containing 1 through to N where N is only known at runtime.
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
To me it feels like there should be a way of doing this without the loop.
In ES6 using Array from() and keys() methods.
Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Shorter version using spread operator.
[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Start from 1 by passing map function to Array from(), with an object with a length property:
Array.from({length: 10}, (_, i) => i + 1)
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
You can do so:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
or with random values:
Array.apply(null, {length: N}).map(Function.call, Math.random)
result: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765,
0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.5577575915958732, 0.16363654541783035]
Explanation
First, note that Number.call(undefined, N) is equivalent to Number(N), which just returns N. We'll use that fact later.
Array.apply(null, [undefined, undefined, undefined]) is equivalent to Array(undefined, undefined, undefined), which produces a three-element array and assigns undefined to each element.
How can you generalize that to N elements? Consider how Array() works, which goes something like this:
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;
}
Since ECMAScript 5, Function.prototype.apply(thisArg, argsArray) also accepts a duck-typed array-like object as its second parameter. If we invoke Array.apply(null, { length: N }), then it will execute
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
Now we have an N-element array, with each element set to undefined. When we call .map(callback, thisArg) on it, each element will be set to the result of callback.call(thisArg, element, index, array). Therefore, [undefined, undefined, …, undefined].map(Number.call, Number) would map each element to (Number.call).call(Number, undefined, index, array), which is the same as Number.call(undefined, index, array), which, as we observed earlier, evaluates to index. That completes the array whose elements are the same as their index.
Why go through the trouble of Array.apply(null, {length: N}) instead of just Array(N)? After all, both expressions would result an an N-element array of undefined elements. The difference is that in the former expression, each element is explicitly set to undefined, whereas in the latter, each element was never set. According to the documentation of .map():
callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
Therefore, Array(N) is insufficient; Array(N).map(Number.call, Number) would result in an uninitialized array of length N.
Compatibility
Since this technique relies on behaviour of Function.prototype.apply() specified in ECMAScript 5, it will not work in pre-ECMAScript 5 browsers such as Chrome 14 and Internet Explorer 9.
Multiple ways using ES6
Using spread operator (...) and keys method
[ ...Array(N).keys() ].map( i => i+1);
Fill/Map
Array(N).fill().map((_, i) => i+1);
Array.from
Array.from(Array(N), (_, i) => i+1)
Array.from and { length: N } hack
Array.from({ length: N }, (_, i) => i+1)
Note about generalised form
All the forms above can produce arrays initialised to pretty much any desired values by changing i+1 to expression required (e.g. i*2, -i, 1+i*2, i%2 and etc). If expression can be expressed by some function f then the first form becomes simply
[ ...Array(N).keys() ].map(f)
Examples:
Array.from({length: 5}, (v, k) => k+1);
// [1,2,3,4,5]
Since the array is initialized with undefined on each position, the value of v will be undefined
Example showcasing all the forms
let demo= (N) => {
console.log(
[ ...Array(N).keys() ].map(( i) => i+1),
Array(N).fill().map((_, i) => i+1) ,
Array.from(Array(N), (_, i) => i+1),
Array.from({ length: N }, (_, i) => i+1)
)
}
demo(5)
More generic example with custom initialiser function f i.e.
[ ...Array(N).keys() ].map((i) => f(i))
or even simpler
[ ...Array(N).keys() ].map(f)
let demo= (N,f) => {
console.log(
[ ...Array(N).keys() ].map(f),
Array(N).fill().map((_, i) => f(i)) ,
Array.from(Array(N), (_, i) => f(i)),
Array.from({ length: N }, (_, i) => f(i))
)
}
demo(5, i=>2*i+1)
If I get what you are after, you want an array of numbers 1..n that you can later loop through.
If this is all you need, can you do this instead?
var foo = new Array(45); // create an empty array with length 45
then when you want to use it... (un-optimized, just for example)
for(var i = 0; i < foo.length; i++){
document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>');
}
e.g. if you don't need to store anything in the array, you just need a container of the right length that you can iterate over... this might be easier.
See it in action here: http://jsfiddle.net/3kcvm/
Arrays innately manage their lengths. As they are traversed, their indexes can be held in memory and referenced at that point. If a random index needs to be known, the indexOf method can be used.
This said, for your needs you may just want to declare an array of a certain size:
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
*/
ES6
Spread
Making use of the spread operator (...) and keys method, enables you to create a temporary array of size N to produce the indexes, and then a new array that can be assigned to your variable:
var foo = [ ...Array(N).keys() ];
Fill/Map
You can first create the size of the array you need, fill it with undefined and then create a new array using map, which sets each element to the index.
var foo = Array(N).fill().map((v,i)=>i);
Array.from
This should be initializing to length of size N and populating the array in one pass.
Array.from({ length: N }, (v, i) => i)
In lieu of the comments and confusion, if you really wanted to capture the values from 1..N in the above examples, there are a couple options:
if the index is available, you can simply increment it by one (e.g., ++i).
in cases where index is not used -- and possibly a more efficient way -- is to create your array but make N represent N+1, then shift off the front.
So if you desire 100 numbers:
let arr; (arr=[ ...Array(101).keys() ]).shift()
In ES6 you can do:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
Edit:
Changed Array(45) to Array(N) since you've updated the question.
console.log(
Array(45).fill(0).map((e,i)=>i+1)
);
Use the very popular Underscore _.range method
// _.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;
}
Then called by
var foo = range(1, 5);
There is no built-in way to do this in Javascript, but it's a perfectly valid utility function to create if you need to do it more than once.
Edit: In my opinion, the following is a better range function. Maybe just because I'm biased by LINQ, but I think it's more useful in more cases. Your mileage may vary.
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;
}
the fastest way to fill an Array in v8 is:
[...Array(5)].map((_,i) => i);
result will be: [0, 1, 2, 3, 4]
Performance
Today 2020.12.11 I performed tests on macOS HighSierra 10.13.6 on Chrome v87, Safari v13.1.2 and Firefox v83 for chosen solutions.
Results
For all browsers
solution O (based on while) is the fastest (except Firefox for big N - but it's fast there)
solution T is fastest on Firefox for big N
solutions M,P is fast for small N
solution V (lodash) is fast for big N
solution W,X are slow for small N
solution F is slow
Details
I perform 2 tests cases:
for small N = 10 - you can run it HERE
for big N = 1000000 - you can run it HERE
Below snippet presents all tested solutions A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
function A(N) {
return Array.from({length: N}, (_, i) => i + 1)
}
function B(N) {
return Array(N).fill().map((_, i) => i+1);
}
function C(N) {
return Array(N).join().split(',').map((_, i) => i+1 );
}
function D(N) {
return Array.from(Array(N), (_, i) => i+1)
}
function E(N) {
return Array.from({ length: N }, (_, i) => i+1)
}
function F(N) {
return Array.from({length:N}, Number.call, i => i + 1)
}
function G(N) {
return (Array(N)+'').split(',').map((_,i)=> i+1)
}
function H(N) {
return [ ...Array(N).keys() ].map( i => i+1);
}
function I(N) {
return [...Array(N).keys()].map(x => x + 1);
}
function J(N) {
return [...Array(N+1).keys()].slice(1)
}
function K(N) {
return [...Array(N).keys()].map(x => ++x);
}
function L(N) {
let arr; (arr=[ ...Array(N+1).keys() ]).shift();
return arr;
}
function M(N) {
var arr = [];
var i = 0;
while (N--) arr.push(++i);
return arr;
}
function N(N) {
var a=[],b=N;while(b--)a[b]=b+1;
return a;
}
function O(N) {
var a=Array(N),b=0;
while(b<N) a[b++]=b;
return a;
}
function P(N) {
var foo = [];
for (var i = 1; i <= N; i++) foo.push(i);
return foo;
}
function Q(N) {
for(var a=[],b=N;b--;a[b]=b+1);
return a;
}
function R(N) {
for(var i,a=[i=0];i<N;a[i++]=i);
return a;
}
function S(N) {
let foo,x;
for(foo=[x=N]; x; foo[x-1]=x--);
return foo;
}
function T(N) {
return new Uint8Array(N).map((item, i) => i + 1);
}
function U(N) {
return '_'.repeat(5).split('').map((_, i) => i + 1);
}
function V(N) {
return _.range(1, N+1);
}
function W(N) {
return [...(function*(){let i=0;while(i<N)yield ++i})()]
}
function X(N) {
function sequence(max, step = 1) {
return {
[Symbol.iterator]: function* () {
for (let i = 1; i <= max; i += step) yield i
}
}
}
return [...sequence(N)];
}
[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X].forEach(f=> {
console.log(`${f.name} ${f(5)}`);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"> </script>
This snippet only presents functions used in performance tests - it does not perform tests itself!
And here are example results for chrome
This question has a lot of complicated answers, but a simple one-liner:
[...Array(255).keys()].map(x => x + 1)
Also, although the above is short (and neat) to write, I think the following is a bit faster
(for a max length of:
127, Int8,
255, Uint8,
32,767, Int16,
65,535, Uint16,
2,147,483,647, Int32,
4,294,967,295, Uint32.
(based on the max integer values), also here's more on Typed Arrays):
(new Uint8Array(255)).map(($,i) => i + 1);
Although this solution is also not so ideal, because it creates two arrays, and uses the extra variable declaration "$" (not sure any way to get around that using this method). I think the following solution is the absolute fastest possible way to do this:
for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;
Anytime after this statement is made, you can simple use the variable "arr" in the current scope;
If you want to make a simple function out of it (with some basic verification):
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
);
so, with the above function, the above super-slow "simple one-liner" becomes the super-fast, even-shorter:
range(1,14000);
Using ES2015/ES6 spread operator
[...Array(10)].map((_, i) => i + 1)
console.log([...Array(10)].map((_, i) => i + 1))
You can use this:
new Array(/*any number which you want*/)
.join().split(',')
.map(function(item, index){ return ++index;})
for example
new Array(10)
.join().split(',')
.map(function(item, index){ return ++index;})
will create following array:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
If you happen to be using d3.js in your app as I am, D3 provides a helper function that does this for you.
So to get an array from 0 to 4, it's as easy as:
d3.range(5)
[0, 1, 2, 3, 4]
and to get an array from 1 to 5, as you were requesting:
d3.range(1, 5+1)
[1, 2, 3, 4, 5]
Check out this tutorial for more info.
This is probably the fastest way to generate an array of numbers
Shortest
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]
If you want to start from 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]
Want a function?
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]
WHY?
while is the fastest loop
Direct setting is faster than push
[] is faster than new Array(10)
it's short... look the first code. then look at all other functions in here.
If you like can't live without for
for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]
or
for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
If you are using lodash, you can use _.range:
_.range([start=0], end, [step=1])
Creates an array of numbers
(positive and/or negative) progressing from start up to, but not
including, end. A step of -1 is used if a negative start is specified
without an end or step. If end is not specified, it's set to start
with start then set to 0.
Examples:
_.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);
// ➜ []
the new way to filling Array is:
const array = [...Array(5).keys()]
console.log(array)
result will be: [0, 1, 2, 3, 4]
with ES6 you can do:
// `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)
Very simple and easy to generate exactly 1 - N
const [, ...result] = Array(11).keys();
console.log('Result:', result);
Final Summary report .. Drrruummm Rolll -
This is the shortest code to generate an Array of size N (here 10) without using ES6. Cocco's version above is close but not the shortest.
(function(n){for(a=[];n--;a[n]=n+1);return a})(10)
But the undisputed winner of this Code golf(competition to solve a particular problem in the fewest bytes of source code) is Niko Ruotsalainen . Using Array Constructor and ES6 spread operator . (Most of the ES6 syntax is valid typeScript, but following is not. So be judicious while using it)
[...Array(10).keys()]
https://stackoverflow.com/a/49577331/8784402
With Delta
For javascript
smallest and one-liner
[...Array(N)].map((v, i) => from + i * step);
Examples and other alternatives
Array.from(Array(10).keys()).map(i => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
[...Array(10).keys()].map(i => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
Array(10).fill(0).map((v, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Array(10).fill().map((v, i) => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
[...Array(10)].map((v, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Range Function
const range = (from, to, step) =>
[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
range(0, 9, 2);
//=> [0, 2, 4, 6, 8]
// can also assign range function as static method in Array class (but not recommended )
Array.range = (from, to, step) =>
[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
Array.range(2, 10, 2);
//=> [2, 4, 6, 8, 10]
Array.range(0, 10, 1);
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Array.range(2, 10, -1);
//=> []
Array.range(3, 0, -1);
//=> [3, 2, 1, 0]
As Iterators
class Range {
constructor(total = 0, step = 1, from = 0) {
this[Symbol.iterator] = function* () {
for (let i = 0; i < total; yield from + i++ * step) {}
};
}
}
[...new Range(5)]; // Five Elements
//=> [0, 1, 2, 3, 4]
[...new Range(5, 2)]; // Five Elements With Step 2
//=> [0, 2, 4, 6, 8]
[...new Range(5, -2, 10)]; // Five Elements With Step -2 From 10
//=>[10, 8, 6, 4, 2]
[...new Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]
// Also works with for..of loop
for (i of new Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2
As Generators Only
const Range = function* (total = 0, step = 1, from = 0) {
for (let i = 0; i < total; yield from + i++ * step) {}
};
Array.from(Range(5, -2, -10));
//=> [-10, -12, -14, -16, -18]
[...Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]
// Also works with for..of loop
for (i of Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2
// Lazy loaded way
const number0toInf = Range(Infinity);
number0toInf.next().value;
//=> 0
number0toInf.next().value;
//=> 1
// ...
From-To with steps/delta
using iterators
class Range2 {
constructor(to = 0, step = 1, from = 0) {
this[Symbol.iterator] = function* () {
let i = 0,
length = Math.floor((to - from) / step) + 1;
while (i < length) yield from + i++ * step;
};
}
}
[...new Range2(5)]; // First 5 Whole Numbers
//=> [0, 1, 2, 3, 4, 5]
[...new Range2(5, 2)]; // From 0 to 5 with step 2
//=> [0, 2, 4]
[...new Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]
using Generators
const Range2 = function* (to = 0, step = 1, from = 0) {
let i = 0,
length = Math.floor((to - from) / step) + 1;
while (i < length) yield from + i++ * step;
};
[...Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]
let even4to10 = Range2(10, 2, 4);
even4to10.next().value;
//=> 4
even4to10.next().value;
//=> 6
even4to10.next().value;
//=> 8
even4to10.next().value;
//=> 10
even4to10.next().value;
//=> undefined
For Typescript
class _Array<T> extends Array<T> {
static range(from: number, to: number, step: number): number[] {
return Array.from(Array(Math.floor((to - from) / step) + 1)).map(
(v, k) => from + k * step
);
}
}
_Array.range(0, 9, 1);
Solution for empty array and with just number in array
const arrayOne = new Array(10);
console.log(arrayOne);
const arrayTwo = [...Array(10).keys()];
console.log(arrayTwo);
var arrayThree = Array.from(Array(10).keys());
console.log(arrayThree);
const arrayStartWithOne = Array.from(Array(10).keys(), item => item + 1);
console.log(arrayStartWithOne)
✅ Simply, this worked for me:
[...Array(5)].map(...)
There is another way in ES6, using Array.from which takes 2 arguments, the first is an arrayLike (in this case an object with length property), and the second is a mapping function (in this case we map the item to its index)
Array.from({length:10}, (v,i) => i)
this is shorter and can be used for other sequences like generating even numbers
Array.from({length:10}, (v,i) => i*2)
Also this has better performance than most other ways because it only loops once through the array.
Check the snippit for some comparisons
// 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")
Fast
This solution is probably fastest it is inspired by lodash _.range function (but my is simpler and faster)
let N=10, i=0, a=Array(N);
while(i<N) a[i++]=i;
console.log(a);
Performance advantages over current (2020.12.11) existing answers based on while/for
memory is allocated once at the beginning by a=Array(N)
increasing index i++ is used - which looks is about 30% faster than decreasing index i-- (probably because CPU cache memory faster in forward direction)
Speed tests with more than 20 other solutions was conducted in this answer
Using new Array methods and => function syntax from ES6 standard (only Firefox at the time of writing).
By filling holes with undefined:
Array(N).fill().map((_, i) => i + 1);
Array.from turns "holes" into undefined so Array.map works as expected:
Array.from(Array(5)).map((_, i) => i + 1)
In ES6:
Array.from({length: 1000}, (_, i) => i).slice(1);
or better yet (without the extra variable _ and without the extra slice call):
Array.from({length:1000}, Number.call, i => i + 1)
Or for slightly faster results, you can use Uint8Array, if your list is shorter than 256 results (or you can use the other Uint lists depending on how short the list is, like Uint16 for a max number of 65535, or Uint32 for a max of 4294967295 etc. Officially, these typed arrays were only added in ES6 though). For example:
Uint8Array.from({length:10}, Number.call, i => i + 1)
ES5:
Array.apply(0, {length: 1000}).map(function(){return arguments[1]+1});
Alternatively, in ES5, for the map function (like second parameter to the Array.from function in ES6 above), you can use Number.call
Array.apply(0,{length:1000}).map(Number.call,Number).slice(1)
Or, if you're against the .slice here also, you can do the ES5 equivalent of the above (from ES6), like:
Array.apply(0,{length:1000}).map(Number.call, Function("i","return i+1"))
Array(...Array(9)).map((_, i) => i);
console.log(Array(...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]
It seems the only flavor not currently in this rather complete list of answers is one featuring a generator; so to remedy that:
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
which can be used thus:
gen(4) // [0,1,2,3]
The nice thing about this is you don't just have to increment... To take inspiration from the answer #igor-shubin gave, you could create an array of randoms very easily:
const gen = N => [...(function*(){let i=0;
while(i++<N) yield Math.random()
})()]
And rather than something lengthy operationally expensive like:
const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
// [0,5,10,15,...]
you could instead do:
const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]

Categories