Apakah ada cara di Javascript untuk menulis sesuatu seperti ini dengan mudah:
[1,2,3].times do {
something();
}
Pustaka apa saja yang mungkin mendukung sintaks serupa?
Perbarui: untuk memperjelas - Saya ingin something()
dipanggil 1,2 dan 3 kali masing-masing untuk setiap iterasi elemen array
javascript
jquery
underscore.js
BreakPhreak
sumber
sumber
Jawaban:
Jawaban ini didasarkan pada
Array.forEach
, tanpa perpustakaan apa pun, hanya vanili asli .Untuk menelepon
something()
3 kali pada dasarnya , gunakan:[1,2,3].forEach(function(i) { something(); });
mempertimbangkan fungsi berikut:
function something(){ console.log('something') }
Pukulan keluar akan terjadi
Untuk menjawab pertanyaan ini, berikut adalah cara untuk melakukan panggilan
something()
1, 2 dan 3 kali masing-masing:Ini 2017, Anda dapat menggunakan ES6:
[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => { something() }))
atau di ES5 lama yang bagus:
[1,2,3].forEach(function(i) { Array(i).fill(i).forEach(function() { something() }) }))
Dalam kedua kasus, outpout akan terjadi
Pukulan keluar akan terjadi
(sekali, lalu dua kali, lalu 3 kali)
sumber
something
ini hanya dipanggil 3 kali, harus dipanggil 6 kali.[...Array(i)]
atauArray(i).fill()
, tergantung pada kebutuhan Anda akan indeks yang sebenarnya..forEach(something)
Cukup gunakan satu lingkaran:
var times = 10; for(var i=0; i < times; i++){ doSomething(); }
sumber
Alternatif ES6 yang memungkinkan.
Array.from(Array(3)).forEach((x, i) => { something(); });
Dan, jika Anda ingin "dipanggil masing-masing 1,2 dan 3 kali".
Array.from(Array(3)).forEach((x, i) => { Array.from(Array(i+1)).forEach((x, i2) => { console.log(`Something ${ i } ${ i2 }`) }); });
Memperbarui:
Diambil dari filling-array-with-undefined
Ini tampaknya menjadi cara yang lebih dioptimalkan untuk membuat array awal, saya juga memperbarui ini untuk menggunakan fungsi peta parameter kedua yang disarankan oleh @ felix-eve.
Array.from({ length: 3 }, (x, i) => { something(); });
sumber
Array.from(Array(3)).forEach(something)
Array.from()
memiliki parameter opsional keduamapFn
, yang memungkinkan Anda menjalankan fungsi peta pada setiap elemen array, jadi tidak perlu menggunakan forEach. Anda hanya dapat melakukan:Array.from({length: 3}, () => somthing() )
Karena Anda menyebutkan Underscore:
Dengan asumsi
f
adalah fungsi yang ingin Anda panggil:_.each([1,2,3], function (n) { _.times(n, f) });
akan melakukan triknya. Misalnya, dengan
f = function (x) { console.log(x); }
, Anda akan mendapatkan konsol Anda:0 0 1 0 1 2
sumber
_(3).times(function(n){return n;});
harus melakukan triknya. Lihat dokumentasinya di sini.Dengan lodash :
_.each([1, 2, 3], (item) => { doSomeThing(item); }); //Or: _.each([1, 2, 3], doSomeThing);
Atau jika Anda ingin melakukan sesuatu N kali :
const N = 10; _.times(N, () => { doSomeThing(); }); //Or shorter: _.times(N, doSomeThing);
Lihat tautan ini untuk
lodash
instalasisumber
Buat Array dan
fill
semua item denganundefined
begitumap
metode bisa bekerja:// run 5 times: Array(5).fill().map((item, i)=>{ console.log(i) // print index })
Jika Anda ingin membuat yang di atas lebih "dekleratif", solusi berbasis opini saya saat ini adalah:
Tampilkan cuplikan kode
const iterate = times => callback => Array(times).fill().map((n,i) => callback(i)) iterate(3)(console.log)
Menggunakan loop sekolah tua (terbalik):
// run 5 times: for( let i=5; i--; ) console.log(i)
Atau sebagai deklaratif "while" :
Tampilkan cuplikan kode
const times = count => callback => { while(count--) callback(count) } times(3)(console.log)
sumber
Anda juga dapat melakukan hal yang sama dengan merusak sebagai berikut
[...Array(3)].forEach( _ => console.log('do something'));
atau jika Anda membutuhkan index
[...Array(3)].forEach(( _, index) => console.log('do something'));
sumber
Jika Anda tidak dapat menggunakan Underscorejs, Anda dapat menerapkannya sendiri. Dengan melampirkan metode baru ke prototipe Angka dan String, Anda dapat melakukannya seperti ini (menggunakan fungsi panah 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) );
Anda hanya perlu membuat ekspresi fungsi (dengan nama apa pun) dan menetapkannya ke nama properti apa pun (pada prototipe) yang ingin Anda akses sebagai:
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;
sumber
Ada perpustakaan fantastis bernama Ramda, yang mirip dengan Underscore dan Lodash, tetapi lebih bertenaga.
const R = require('ramda'); R.call(R.times(() => { console.log('do something') }), 5);
Ramda mengandung banyak fungsi yang bermanfaat. Lihat dokumentasi Ramda
sumber
Anda dapat menggunakan length of array untuk mengeksekusi berapa kali tugas Anda.
var arr = [1,2,3]; for(var i=0; i < arr.length; i++){ doSomething(); }
atau
var arr = [1,2,3]; do { } while (i++ < arr.length);
sumber
kamu bisa memakai
Array.forEach
contoh:
function logArrayElements(element, index, array) { console.log("a[" + index + "] = " + element); } [2, 5, 9].forEach(logArrayElements)
atau dengan jQuery
$.each([52, 97], function(index, value) { alert(index + ': ' + value); });
http://api.jquery.com/jQuery.each/
sumber
forEach
hanya didukung di IE dari versi 9: 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(); } } }
Anda bisa menyebutnya seperti ini:
times(3,4); times(1,2,3,4); times(1,3,5,7,9);
sumber
// calls doSomething 42 times Array( 42 ).join( "x" ).split( "" ).forEach( doSomething );
dan
// creates 42 somethings var somethings = Array( 42 ).join( "x" ).split( "" ).map( () => buildSomething(); );
atau (melalui https://stackoverflow.com/a/20066663/275501 )
Array.apply(null, {length: 42}).forEach( doSomething );
sumber
var times = [1,2,3]; for(var i = 0; i < times.length; i++) { for(var j = 0; j < times[i];j++) { // do something } }
Menggunakan jQuery
.each()
$([1,2,3]).each(function(i, val) { for(var j = 0; j < val;j++) { // do something } });
ATAU
var x = [1,2,3]; $(x).each(function(i, val) { for(var j = 0; j < val;j++) { // do something } });
EDIT
Anda dapat melakukan seperti di bawah ini dengan JS murni:
var times = [1,2,3]; times.forEach(function(i) { // do something });
sumber
Cukup gunakan loop bersarang (mungkin tertutup dalam suatu fungsi)
function times( fct, times ) { for( var i=0; i<times.length; ++i ) { for( var j=0; j<times[i]; ++j ) { fct(); } } }
Kemudian sebut saja seperti ini:
times( doSomething, [1,2,3] );
sumber
Semua jawaban ini bagus dan bagus dan IMO @Andreas adalah yang terbaik, tetapi sering kali di JS kami harus melakukan hal-hal secara asinkron, dalam hal ini, asinkron telah Anda bahas:
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 });
Fitur 'waktu' ini tidak terlalu berguna untuk sebagian besar kode aplikasi, tetapi seharusnya berguna untuk pengujian.
sumber
const loop (fn, times) => { if (!times) { return } fn() loop(fn, times - 1) } loop(something, 3)
sumber
Diberikan sebuah fungsi
something
:function something() { console.log("did something") }
Dan metode baru
times
ditambahkan keArray
prototipe:Array.prototype.times = function(f){ for(v of this) for(var _ of Array(v)) f(); }
Kode ini:
[1,2,3].times(something)
Keluaran ini:
Yang saya pikir menjawab pertanyaan Anda yang diperbarui (5 tahun kemudian) tetapi saya bertanya-tanya seberapa berguna memiliki pekerjaan ini pada array? Bukankah efeknya sama dengan memanggil
[6].times(something)
, yang pada gilirannya dapat ditulis sebagai:for(_ of Array(6)) something();
(meskipun penggunaan
_
sebagai variabel sampah mungkin akan mengganggu lodash atau garis bawah jika Anda menggunakannya)sumber
let
sebagaifor (let _ of Array(6)) something()
untuk mencegah clobbering lodash di luar setidaknya.Array.from (ES6)
function doSomthing() { ... }
Gunakan seperti ini:
Array.from(Array(length).keys()).forEach(doSomthing);
Atau
Array.from({ length }, (v, i) => i).forEach(doSomthing);
Atau
// array start counting from 1 Array.from({ length }, (v, i) => ++i).forEach(doSomthing);
sumber
Menggunakan
Array.from
dan.forEach
.let length = 5; Array.from({length}).forEach((v, i) => { console.log(`#${i}`); });
sumber
Dengan asumsi kita dapat menggunakan beberapa sintaks ES6 seperti operator penyebaran, kita akan ingin melakukan sesuatu sebanyak jumlah semua angka dalam koleksi.
Dalam hal ini, jika waktu sama dengan
[1,2,3]
, jumlah total waktunya adalah 6, yaitu 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
Posting ini akan membantu jika logika di balik pembuatan dan penyebaran array tidak terlihat.
sumber
Implementasi TypeScript:
Bagi Anda yang tertarik dengan cara mengimplementasikan
String.times
danNumber.times
dengan cara yang termasuk tipe aman dan bekerja denganthisArg
, ini dia: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(() => {}) }
Tautan ke TypeScript Playground dengan beberapa contoh dapat ditemukan di sini
Posting ini mengimplementasikan solusi yang diposting oleh: Andreas Bergström , vinyll , Ozay Duman , & SeregPie
sumber