developer tip

1… N을 포함하는 배열을 만드는 방법

optionbox 2020. 9. 28. 08:59
반응형

1… N을 포함하는 배열을 만드는 방법


N은 런타임에만 알려진 1에서 N까지 포함하는 JavaScript 배열을 만들기 위해 아래에 대한 대안을 찾고 있습니다.

var foo = [];

for (var i = 1; i <= N; i++) {
   foo.push(i);
}

나에게 루프없이 이것을 할 수있는 방법이 있어야한다고 느낀다.


내가 원하는 것을 얻으면 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/


ES6 에서 Array from ()keys () 메서드를 사용합니다.

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]

그렇게 할 수 있습니다.

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.8377588465809822, 0.5577575915958732, 0.16363654541783035]

설명

첫째, 주 Number.call(undefined, N)에 해당 Number(N)하는 단지 반환 N. 우리는 나중에 그 사실을 사용할 것입니다.

Array.apply(null, [undefined, undefined, undefined])Array(undefined, undefined, undefined)요소가 3 개인 배열을 생성하고 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;
}

이제 각 요소가로 설정된 N 요소 배열이 undefined있습니다. .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 요소 배열이 생성됩니다. 차이점은 전자 식에서는 각 요소가 명시 적 으로 정의되지 않은 것으로 설정 되는 반면 후자에서는 각 요소가 설정되지 않았다는 것입니다. 문서에 따르면 .map():

callback값이 할당 된 배열의 인덱스에 대해서만 호출됩니다. 삭제되었거나 값이 할당되지 않은 인덱스에 대해서는 호출되지 않습니다.

따라서 Array(N)충분하지 않습니다. Array(N).map(Number.call, Number)길이 N 의 초기화되지 않은 배열이 생성됩니다 .

적합성

이 기술은 Function.prototype.apply()ECMAScript 5 지정된 동작에 의존하기 때문에 Chrome 14 및 Internet Explorer 9와 같은 ECMAScript 5 이전 브라우저 에서는 작동하지 않습니다 .


ES6의 간단하고 간단한 방법 :

Array.from({length: 5}, (v, k) => k+1); 
// [1,2,3,4,5]

따라서 :

    Array.from({length: N}, (v, k) => k+1);  
   // [1,2,3,...,N]

이 배열로 초기화되기 때문에, undefined각 위치에서의 값이 v될 것이다undefined

const range = (N) => Array.from({length: N}, (v, k) => k+1) ;

console.log(
  range(5)
)


배열은 본질적으로 길이를 관리합니다. 순회 될 때 인덱스를 메모리에 보관하고 해당 지점에서 참조 할 수 있습니다. 임의 인덱스를 알아야하는 경우 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
*/


ES6

확산

확산 연산자 ( ...)와 keys메서드를 사용하면 크기 N의 임시 배열을 만들어 인덱스를 생성 한 다음 변수에 할당 할 수있는 새 배열을 만들 수 있습니다.

var foo = [ ...Array(N).keys() ];

채우기 / 맵

먼저 필요한 배열의 크기를 만들고 undefined로 채운 다음 map각 요소를 인덱스로 설정 하는를 사용하여 새 배열을 만들 수 있습니다 .

var foo = Array(N).fill().map((v,i)=>i);

Array.from

이것은 크기 N의 길이로 초기화되고 한 번에 배열을 채워야합니다.

Array.from({ length: N }, (v, i) => i)

ES6에서는 다음을 수행 할 수 있습니다.

Array(N).fill().map((e,i)=>i+1);

http://jsbin.com/molabiluwa/edit?js, 콘솔

편집 : 변경 Array(45)Array(N)당신이 질문을 업데이 트했습니다 때문이다.

console.log(
  Array(45).fill(0).map((e,i)=>i+1)
);


매우 널리 사용되는 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;
}

Arrayv8 을 채우는 가장 빠른 방법 은 다음과 같습니다.

[...Array(5)].map((_,i) => i);

결과는 다음과 같습니다. [0, 1, 2, 3, 4]


이것을 사용할 수 있습니다 :

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]

이 질문에는 많은 복잡한 답이 있지만 한 줄로 간단합니다.

[...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);

처럼 앱에서 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]

자세한 내용은 이 튜토리얼확인하십시오 .


ES6이 트릭을 수행합니다.

[...Array(12).keys()]

결과를 확인하십시오.

[...Array(12).keys()].map(number => console.log(number))


이것은 아마도 숫자 배열을 생성하는 가장 빠른 방법 일 것입니다

최단

var a=[],b=N;while(b--)a[b]=b+1;

인라인

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]

왜?

  1. while 가장 빠른 루프

  2. 직접 설정이보다 빠릅니다. push

  3. [] 보다 빠릅니다 new Array(10)

  4. 짧습니다 ... 첫 번째 코드를보세요. 그런 다음 여기에있는 다른 모든 기능을 살펴보십시오.

당신이 좋아하는 경우없이 살 수 없다 에 대한

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]

ES2015 / ES6 스프레드 연산자 사용

[...Array(10)].map((_, i) => i + 1)

console.log([...Array(10)].map((_, i) => i + 1))


lodash를 사용하는 경우 _.range 사용할 수 있습니다 .

_.range([start=0], end, [step=1])

시작부터 끝까지 진행하는 숫자 (양수 및 / 또는 음수) 배열을 만듭니다. 끝 또는 단계없이 음수 시작이 지정된 경우 -1 단계가 사용됩니다. end를 지정하지 않으면 start로 시작하고 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);
// ➜ []

채우는 새로운 방법 Array은 다음과 같습니다.

const array = [...Array(5).keys()]
console.log(array)

결과는 다음과 같습니다. [0, 1, 2, 3, 4]


최종 요약 보고서 .. Drrruummm Rolll-

이것은 ES6을 사용하지 않고 크기 N (여기서는 10)의 배열을 생성하는 가장 짧은 코드 입니다. 위의 Cocco 버전은 비슷하지만 가장 짧지는 않습니다.

(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()]

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")


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)

for(var i,a=[i=0];i<10;a[i++]=i);

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


Iterable version using a generator function that doesn't modify Number.prototype.

function sequence(max, step = 1) {
  return {
    [Symbol.iterator]: function* () {
      for (let i = 1; i <= max; i += step) yield i
    }
  }
}

console.log([...sequence(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})()]

A little bit simpler than the string variant:

// create range by N
Array(N).join(0).split(0);

// create a range starting with 0 as the value
Array(7).join(0).split(0).map((v, i) => i + 1) // [1, 2, 3, 4, 5, 6, 7]

Update (1/4/2018): Updated to address the exact OP question. Thanks @lessless for calling this out!


Just another ES6 version.

By making use of Array.from second optional argument:

Array.from(arrayLike[, mapFn[, thisArg]])

We can build the numbered array from the empty Array(10) positions:

Array.from(Array(10), (_, i) => i)

var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);


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)

The following function returns an array populated with numbers:

var createArrayOfNumbers = function (n) {
    return Array.apply(null, new Array(n)).map(function (empty, index) {
        return index;
    });
};

Note that an array created with the array constructor consists of holes, so it cannot be traversed with array functions like map. Hence using the Array.apply function.


Using ES6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);

Object.keys(Array.apply(0, Array(3))).map(Number)

Returns [0, 1, 2]. Very similar to Igor Shubin's excellent answer, but with slightly less trickery (and one character longer).

Explanation:

  • Array(3) // [undefined × 3] Generate an array of length n=3. Unfortunately this array is almost useless to us, so we have to…
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined] make the array iterable. Note: null's more common as apply's first arg but 0's shorter.
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] then get the keys of the array (works because Arrays are the typeof array is an object with indexes for keys.
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] and map over the keys, converting strings to numbers.

You can use a function generator or function* expression. Here's [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function] And a reference to the function generator link to [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function].

let a = 1, b = 10;

function* range(a, b) { for (var i = a; i <= b; ++i) yield i; }

Array.from(range(a, b)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

[...range(a, b)] // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

참고URL : https://stackoverflow.com/questions/3746725/how-to-create-an-array-containing-1-n

반응형