JavaScriptにこのようなものを簡単に書く方法はありますか:
[1,2,3].times do {
something();
}
同様の構文をサポートする可能性のあるライブラリはありますか?
更新:明確にするために- something()
各配列要素の反復ごとにそれぞれ1、2、3回呼び出されたい
JavaScriptにこのようなものを簡単に書く方法はありますか:
[1,2,3].times do {
something();
}
同様の構文をサポートする可能性のあるライブラリはありますか?
更新:明確にするために- something()
各配列要素の反復ごとにそれぞれ1、2、3回呼び出されたい
回答:
この回答はArray.forEach
、ライブラリを使用せず、ネイティブバニラのみに基づいています。
基本的にsomething()
3回呼び出すには、次を使用します。
[1,2,3].forEach(function(i) {
something();
});
次の機能を検討します。
function something(){ console.log('something') }
発信者は
something
something
something
この質問を完了するために、something()
それぞれ1、2、3回電話をかける方法を次に示します。
[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => {
something()
}))
[1,2,3].forEach(function(i) {
Array(i).fill(i).forEach(function() {
something()
})
}))
どちらの場合も、outpoutは
発信者は
something
something
something
something
something
something
(1回、2回、3回)
something
と、3回しか呼び出されません。6回呼び出す必要があります。
[...Array(i)]
またはを使用することもできArray(i).fill()
ます。
.forEach(something)
ループを使うだけです:
var times = 10;
for(var i=0; i < times; i++){
doSomething();
}
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 }`)
});
});
fill -arrays-with-undefinedから取得
これは、初期配列を作成するためのより最適化された方法のようです。@ felix-eveによって提案された2番目のパラメーターマップ関数を使用するように更新しました。
Array.from({ length: 3 }, (x, i) => {
something();
});
Array.from(Array(3)).forEach(something)
Array.from()
オプションの2番目のパラメーターmapFn
があります。これにより、配列の各要素に対してマップ関数を実行できるため、forEachを使用する必要はありません。あなただけ行うことができます:Array.from({length: 3}, () => somthing() )
アンダースコアについて言及したので:
想定するのf
は、呼び出す関数です。
_.each([1,2,3], function (n) { _.times(n, f) });
トリックを行います。たとえばf = function (x) { console.log(x); }
、を使用すると、コンソールが表示されます。
0 0 1 0 1 2
_(3).times(function(n){return n;});
トリックを行う必要があります。こちらのドキュメントをご覧ください。
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;
ラムダと呼ばれる素晴らしいライブラリがあります。これは、アンダースコアやロダッシュに似ていますが、より強力です。
const R = require('ramda');
R.call(R.times(() => {
console.log('do something')
}), 5);
Ramdaには便利な機能がたくさん含まれています。Ramdaのドキュメントを参照
あなたは使うことができます
Array.forEach
例:
function logArrayElements(element, index, array) {
console.log("a[" + index + "] = " + element);
}
[2, 5, 9].forEach(logArrayElements)
またはjQueryで
$.each([52, 97], function(index, value) {
alert(index + ': ' + value);
});
forEach
:唯一のバージョン9からIEでサポートされてdeveloper.mozilla.org/en/JavaScript/Reference/Global_Objects/...
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);
// 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 );
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
});
これらの答えはすべてうまくいっており、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
});
これらの「時間」機能は、ほとんどのアプリケーションコードに非常に役立ちますが、テストには役立つはずです。
与えられた関数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();
(ただし、_
ジャンク変数として使用すると、おそらくロダッシュまたはアンダースコアが使用されます)
let
inのfor (let _ of Array(6)) something()
ように使用して、少なくともの外でロダッシュを壊すのを防ぐことができます。
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);
スプレッド演算子のようないくつかの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
この投稿は、配列の構築と展開の背後にあるロジックが明らかでない場合に役立ちます。
TypeScript実装:
実装方法String.times
とNumber.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へのリンクはここにあります
投稿者:この記事を実装ソリューションアンドレアスベルイストローム、vinyll、Ozay豆満江、&SeregPie