<something> N 번 수행 (선언 구문)


96

Javascript에 다음과 같이 쉽게 작성할 수있는 방법이 있습니까?

[1,2,3].times do {
  something();
}

유사한 구문을 지원할 수있는 라이브러리가 있습니까?

업데이트 : 명확히하기 위해- something()각 배열 요소 반복에 대해 각각 1,2 및 3 번 호출하고 싶습니다.


2
JS에는 이와 같은 기능이 없으며 누락 된 상위 5 개 기능이라고 말하고 싶습니다. 무엇보다 소프트웨어 테스트에 매우 유용합니다.
Alexander Mills

답변:


48

이 답변은 Array.forEach라이브러리없이 네이티브 바닐라를 기반으로 합니다.

기본적으로 something()3 번 전화하려면 다음을 사용하세요.

[1,2,3].forEach(function(i) {
  something();
});

다음 기능을 고려하십시오.

function something(){ console.log('something') }

아웃 파우 트는

something
something
something

이 질문을 완료하려면 something()각각 1 번, 2 번, 3 번 전화하는 방법이 있습니다.

2017 년, ES6를 사용할 수 있습니다.

[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => {
  something()
}))

또는 좋은 오래된 ES5에서 :

[1,2,3].forEach(function(i) {
  Array(i).fill(i).forEach(function() {
    something()
  })
}))

두 경우 모두 아웃 파우 트는

아웃 파우 트는

something

something
something

something
something
something

(1 회, 2 회, 3 회)


18
이것은 '뭔가 ()를 1,2,3 번 호출하고 싶습니다'라는 질문의이 부분을 만족시키지 못하기 때문에 틀 렸습니다. 이 코드를 사용하면 something3 번만 호출되며 6 번 호출되어야합니다.
Ian Newson

그렇다면 좋은 시작일지도 모르기 때문에 베스트 답변 으로 선정 된 것 같습니다 .
vinyll

3
당신은 또한 사용할 수 있습니다 [...Array(i)]또는 Array(i).fill()실제 인덱스에 대한 사용자의 요구에 따라.
Guido Bouman

전달 된 인수에 관심이 없다면 다음을 사용하십시오..forEach(something)
kvsm

88

루프를 사용하십시오.

var times = 10;
for(var i=0; i < times; i++){
    doSomething();
}

3
감사합니다! 나는 선언적 구문에서 (단지 재스민 등 같은) 혜택 싶습니다
BreakPhreak

바로,하지만 기능 선언적 구문도있을 것이기 루프 훨씬 더
알렉산더 밀스

71

가능한 ES6 대안.

Array.from(Array(3)).forEach((x, i) => {
  something();
});

그리고 "각각 1,2 및 3 번 호출"을 원할 경우.

Array.from(Array(3)).forEach((x, i) => {
  Array.from(Array(i+1)).forEach((x, i2) => {
    console.log(`Something ${ i } ${ i2 }`)
  });
});

최신 정보:

정의되지 않은 채우기 배열 에서 가져옴

이것은 초기 배열을 만드는 더 최적화 된 방법 인 것 같습니다. 또한 @ felix-eve가 제안한 두 번째 매개 변수 맵 기능을 사용하도록 업데이트했습니다.

Array.from({ length: 3 }, (x, i) => {
  something();
});

3
나는 당신이 무언가를 빨리 스크립팅하는 경우 괜찮다고 말함으로써 이것을 경고해야하지만, 성능은 끔찍하므로 집중적 인 재귀 나 프로덕션에서는 사용하지 마십시오.
nverba

당신이 ES6을위한 거라면, 당신은 대신에 대해 forEach ()의지도 ()를 사용할 수 있습니다
앤디 포드

3
간결함이 목표 인 경우 (실제로 그렇지 않더라도) 함수를 호출하는 대신 전달하십시오.Array.from(Array(3)).forEach(something)
kvsm

1
반응 표현 렌더링에서도 작동합니다.
Josh Sharkey

4
Array.from()선택 사항 인 두 번째 매개 변수 mapFn를 사용하여 배열의 각 요소에 대해 맵 함수를 실행할 수 있으므로 forEach를 사용할 필요가 없습니다. 다음과 같이 할 수 있습니다.Array.from({length: 3}, () => somthing() )
Felix Eve

19

밑줄을 언급 한 이후 :

f호출하려는 함수가 다음과 같다고 가정 합니다.

_.each([1,2,3], function (n) { _.times(n, f) });

트릭을 할 것입니다. 예를 들어를 사용 f = function (x) { console.log(x); }하면 콘솔이 표시됩니다. 0 0 1 0 1 2


사실, 나는 당신이 별거를 원한다고 생각했습니다.
ggozad

2
_(3).times(function(n){return n;});트릭을해야합니다. 여기에서 문서를 참조하십시오.

18

lodash 와 함께 :

_.each([1, 2, 3], (item) => {
   doSomeThing(item);
});

//Or:
_.each([1, 2, 3], doSomeThing);

또는 무언가를 N 번 하고 싶다면 :

const N = 10;
_.times(N, () => {
   doSomeThing();
});

//Or shorter:
_.times(N, doSomeThing);

참조 링크 에 대한 lodash설치


14

이렇게 방법으로 배열 및 fill모든 항목을 만들 수 있습니다.undefinedmap

Array.fill IE를 지원하지 않습니다

// run 5 times:
Array(5).fill().map((item, i)=>{ 
   console.log(i) // print index
})

위의 내용을 좀 더 "허용"하고 싶다면 현재 내 의견 기반 솔루션은 다음과 같습니다.


구식 (역방향) 루프 사용 :

// run 5 times:
for( let i=5; i--; )
   console.log(i) 

또는 선언적 "while" :


1
uuid를 복제하지 않도록하기 위해 uuid 함수를 50k 번 실행했습니다 . 그래서 나는 단지 킥을 위해 상단 루프와 하단을 프로파일 링했으며, 멍청하지 않은 경우 크롬 개발 도구를 사용하여 정상적인 페이지로드 중간에 실행 중일 때 Array.indexOf ()를 사용하여 50k uuid를 생성 하는 것과 비교하여 ~ 12 억이된다고 생각합니다 . newschool = 1st-5561.2ms 2nd-5426.8ms | oldschool = 1st-4966.3ms / 2nd-4929.0ms 만약 u가 10 억 + 범위에 있지 않다면 u는 무언가를하기 위해 200, 1k, 심지어 10k 번 실행하는 차이를 결코 알아 차리지 못할 것입니다. 누군가 나처럼 호기심이 많을 것 같았다.
rifi2k

그것은 정확하고 수년 동안 알려져 왔습니다. 속도 이점이 아니라 구형 브라우저의 지원을 위해 다른 접근 방식이 제시되었습니다.
vsync 2019

3
분명히이 스레드를 읽는 모든 사람들은 속도를 비교하기 위해 예제를 제시하지 않았다는 것을 알고 있습니다. 나는 그것들을 사용하여 약간의 테스트를 실행하고 길을 따라가는 누군가가 흥미로울 수있는 정보를 공유 할 것이라고 생각했습니다. 나는 단지 정보를 표시하고 어쨌든 몇 ms 안에 끝날 몇 가지 일을 할 때 루프의 속도에 땀을 흘리지 않도록 알림을주는 질문에 실제로 대답하지 않았기 때문에 실제로 정확하지 않습니다. 1 년 전의 동일한 테스트 즉, 브라우저가 항상 변경되기 때문에 50 % 더 느릴 수 있기 때문에 실제로 알려지지 않았습니다.
rifi2k

10

다음과 같이 디스트 럭처링으로 동일한 작업을 수행 할 수도 있습니다.

[...Array(3)].forEach( _ => console.log('do something'));

또는 색인이 필요한 경우

[...Array(3)].forEach(( _, index) => console.log('do something'));

8

Underscorejs를 사용할 수 없다면 직접 구현할 수 있습니다. 새 메서드를 Number 및 String 프로토 타입에 연결하면 다음과 같이 할 수 있습니다 (ES6 화살표 함수 사용).

// With String
"5".times( (i) => console.log("number "+i) );

// With number variable
var five = 5;
five.times( (i) => console.log("number "+i) );

// With number literal (parentheses required)
(5).times( (i) => console.log("number "+i) );

(어떤 이름의) 함수 표현식을 생성하고이를 액세스하려는 속성 이름 (프로토 타입에서)에 할당하기 만하면됩니다.

var timesFunction = function(callback) {
  if (typeof callback !== "function" ) {
    throw new TypeError("Callback is not a function");
  } else if( isNaN(parseInt(Number(this.valueOf()))) ) {
    throw new TypeError("Object is not a valid number");
  }
  for (var i = 0; i < Number(this.valueOf()); i++) {
    callback(i);
  }
};

String.prototype.times = timesFunction;
Number.prototype.times = timesFunction;

1
프로토 타입을 패치하는 것이 얼마나 나쁜지 다시 조사해야하지만 일반적으로 괜찮습니다.
알렉산더 밀스

2

Underscore 및 Lodash와 유사하지만 더 강력한 Ramda라는 환상적인 라이브러리가 있습니다.

const R = require('ramda');

R.call(R.times(() => {
    console.log('do something')
}), 5);

Ramda에는 유용한 기능이 많이 포함되어 있습니다. Ramda 문서 참조


저는이 라이브러리를 현대적이고 우아한 FP 솔루션으로 좋아합니다.
momocow

1

배열의 길이를 사용하여 작업을 여러 번 실행할 수 있습니다.

var arr = [1,2,3];

for(var i=0; i < arr.length; i++){
    doSomething();
}

또는

 var arr = [1,2,3];

 do
 {


 }
 while (i++ < arr.length);


1
times = function () {
    var length = arguments.length;
    for (var i = 0; i < length ; i++) {
        for (var j = 0; j < arguments[i]; j++) {
            dosomthing();
        }
    }
}

다음과 같이 부를 수 있습니다.

times(3,4);
times(1,2,3,4);
times(1,3,5,7,9);

+1-이것은 매개 변수의 양이 가변적 인 함수를 호출하는 네이티브 JavaScript 기능을 활용합니다. 추가 라이브러리가 필요하지 않습니다. 니스 솔루션
RustyTheBoyRobot

1
// calls doSomething 42 times
Array( 42 ).join( "x" ).split( "" ).forEach( doSomething );

// creates 42 somethings
var somethings = Array( 42 ).join( "x" ).split( "" ).map( () => buildSomething(); );

또는 ( https://stackoverflow.com/a/20066663/275501을 통해 )

Array.apply(null, {length: 42}).forEach( doSomething );

1
var times = [1,2,3];

for(var i = 0; i < times.length;  i++) {
  for(var j = 0; j < times[i];j++) {
     // do something
  }
}

jQuery 사용 .each()

$([1,2,3]).each(function(i, val) {
  for(var j = 0; j < val;j++) {
     // do something
  }
});

또는

var x = [1,2,3];

$(x).each(function(i, val) {
  for(var j = 0; j < val;j++) {
     // do something
  }
});

편집하다

순수 JS로 아래와 같이 할 수 있습니다.

var times = [1,2,3];
times.forEach(function(i) {
   // do something
});

0

중첩 된 루프를 사용하십시오 (함수로 묶일 수도 있음).

function times( fct, times ) {
  for( var i=0; i<times.length; ++i ) {
    for( var j=0; j<times[i]; ++j ) {
      fct();
    }
  }
}

그런 다음 다음과 같이 호출하십시오.

times( doSomething, [1,2,3] );

0

이 답변은 모두 훌륭하고 IMO @Andreas가 최고이지만 JS에서 여러 번 비동기식으로 작업을 수행해야합니다.이 경우 비동기로 처리했습니다.

http://caolan.github.io/async/docs.html#times

const async = require('async');

async.times(5, function(n, next) {
    createUser(n, function(err, user) {
        next(err, user);
    });
}, function(err, users) {
    // we should now have 5 users
});

이러한 '시간'기능은 대부분의 응용 프로그램 코드에 그다지 유용하지 않지만 테스트에는 유용해야합니다.


0
const loop (fn, times) => {
  if (!times) { return }
  fn()
  loop(fn, times - 1)
}

loop(something, 3)

0

주어진 함수 something:

function something() { console.log("did something") }

프로토 타입에 times추가 된 새로운 방법 Array:

Array.prototype.times = function(f){
  for(v of this) 
    for(var _ of Array(v))
      f();
}

이 코드 :

[1,2,3].times(something)

다음을 출력합니다.

did something
did something
did something
did something
did something
did something

어떤 내가 생각하는이 업데이트 된 질문을 (5 년 이상) 대답하지만 난 그것을 배열에이 일을하는 것이 얼마나 도움이 궁금해? 그 효과는 다음과 같이 [6].times(something)쓸 수 있는를 호출하는 것과 같지 않을까요?

for(_ of Array(6)) something();

( _정크 변수로 사용하면 사용하는 경우 lodash 또는 밑줄이 흐려질 수 있습니다.)


1
네이티브 JS 객체에 커스텀 메소드를 추가하는 것은 나쁜 습관으로 간주됩니다.
오르 엘롬

최소한의 외부에서 lodash가 막히는 것을 방지하기 위해 letin for (let _ of Array(6)) something()으로 사용할 수 있습니다 .
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

0

Array.from (ES6)

function doSomthing() {
    ...
}

다음과 같이 사용하십시오.

Array.from(Array(length).keys()).forEach(doSomthing);

또는

Array.from({ length }, (v, i) => i).forEach(doSomthing);

또는

// array start counting from 1
Array.from({ length }, (v, i) => ++i).forEach(doSomthing);

0

사용 Array.from하고 .forEach.

let length = 5;
Array.from({length}).forEach((v, i) => {
  console.log(`#${i}`);
});


0

스프레드 연산자와 같은 ES6 구문을 사용할 수 있다고 가정하면 컬렉션에있는 모든 숫자의 합계만큼 많은 작업을 수행하려고합니다.

이 경우 시간이 [1,2,3]이면 총 횟수는 6, 즉 1 + 2 + 3이됩니다.

/**
 * @param {number[]} times
 * @param {cb} function
 */
function doTimes(times, cb) {
  // Get the sum of all the times
  const totalTimes = times.reduce((acc, time) => acc + time);
  // Call the callback as many times as the sum
  [...Array(totalTimes)].map(cb);
}

doTimes([1,2,3], () => console.log('something'));
// => Prints 'something' 6 times

이 게시물은 배열을 구성하고 확산하는 논리가 명확하지 않은 경우 유용 합니다.


0

TypeScript 구현 :

구현하는 방법에 관심이있는 분들을 위해 String.timesNumber.times유형의 안전과 함께 작동하는 방식으로 thisArg, 여기에 나중에 가서 :

declare global {
    interface Number {
        times: (callbackFn: (iteration: number) => void, thisArg?: any) => void;
    }
    interface String {
        times: (callbackFn: (iteration: number) => void, thisArg?: any) => void;
    }
}

Number.prototype.times = function (callbackFn, thisArg) {
    const num = this.valueOf()
    if (typeof callbackFn !== "function" ) {
        throw new TypeError("callbackFn is not a function")
    }
    if (num < 0) {
        throw new RangeError('Must not be negative')
    }
    if (!isFinite(num)) {
        throw new RangeError('Must be Finite')
    }
    if (isNaN(num)) {
        throw new RangeError('Must not be NaN')
    }

    [...Array(num)].forEach((_, i) => callbackFn.bind(thisArg, i + 1)())
    // Other elegant solutions
    // new Array<null>(num).fill(null).forEach(() => {})
    // Array.from({length: num}).forEach(() => {})
}

String.prototype.times = function (callbackFn, thisArg) {
    let num = parseInt(this.valueOf())
    if (typeof callbackFn !== "function" ) {
        throw new TypeError("callbackFn is not a function")
    }
    if (num < 0) {
        throw new RangeError('Must not be negative')
    }
    if (!isFinite(num)) {
        throw new RangeError('Must be Finite')
    }
    // num is NaN if `this` is an empty string 
    if (isNaN(num)) {
        num = 0
    }

    [...Array(num)].forEach((_, i) => callbackFn.bind(thisArg, i + 1)())
    // Other elegant solutions
    // new Array<null>(num).fill(null).forEach(() => {})
    // Array.from({length: num}).forEach(() => {})
}

몇 가지 예제 가있는 TypeScript Playground에 대한 링크 는 여기 에서 찾을 수 있습니다.

이 게시물은 Andreas Bergström , vinyll , Ozay Duman , & SeregPie가 게시 한 솔루션을 구현합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.