जावास्क्रिप्ट में एक मनमाना लंबाई शून्य भरा सरणी बनाने का सबसे कुशल तरीका क्या है?
let i = 0; Array.from(Array(10), ()=>i++);
जावास्क्रिप्ट में एक मनमाना लंबाई शून्य भरा सरणी बनाने का सबसे कुशल तरीका क्या है?
let i = 0; Array.from(Array(10), ()=>i++);
जवाबों:
ईएस 6 पेश करता है Array.prototype.fill
। इसका उपयोग इस तरह किया जा सकता है:
new Array(len).fill(0);
यकीन नहीं है कि यह तेज़ है, लेकिन मुझे यह पसंद है क्योंकि यह छोटा और आत्म-वर्णन है।
यह अभी भी IE ( संगतता की जांच ) में नहीं है, लेकिन एक पॉलीफ़िल उपलब्ध है ।
new Array(len)
दर्द धीमा है। (arr = []).length = len; arr.fill(0);
सबसे तेज घोल के बारे में कहीं भी देखा जाता है ... या कम से कम बंधा हुआ
arr = Array(n)
और (arr = []).length = n
युक्ति के अनुसार पहचान का व्यवहार करें। कुछ कार्यान्वयन में एक तेज़ हो सकता है, लेकिन मुझे नहीं लगता कि कोई बड़ा अंतर है।
(arr = []).length = 1000;
खिलाफ इस लाइन का उपयोग करके arr = new Array(1000);
इसे Chrome और FF दोनों में टेस्ट करें ... new
बहुत धीमा है। अब, सरणी की लंबाई छोटी है .. कहते हैं <50 या वहाँ के बारे में ... तो new Array()
बेहतर प्रदर्शन करने लगता है। लेकिन ..
arr.fill(0)
... सब कुछ बदल जाता है। अब, new Array()
ज्यादातर मामलों में उपयोग तेज है , जब आप सरणी आकार> 100000 ... को छोड़कर, तब आप फिर से गति में वृद्धि देखना शुरू कर सकते हैं। लेकिन अगर आपको वास्तव में शून्य के साथ इसे पूर्वनिर्मित नहीं करना है और खाली सरणियों के मानक फालिज का उपयोग कर सकते हैं। फिर (arr = []).length = x
ज्यादातर समय मेरे टेस्ट के मामलों में पागल रहता है।
new Array(5).forEach(val => console.log('hi'));
बनाम new Array(5).fill(undefined).forEach(val => console.log('hi'));
।
हालांकि यह एक पुराना धागा है, मैं इसमें अपने 2 सेंट जोड़ना चाहता था। यह सुनिश्चित नहीं है कि यह कितना धीमा / तेज़ है, लेकिन यह एक त्वरित लाइनर है। ये है जो मैं करता हूं:
अगर मैं एक नंबर से प्री-फिल करना चाहता हूं:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
अगर मैं एक स्ट्रिंग के साथ पूर्व-भरना चाहता हूं:
Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
अन्य उत्तर सुझाए गए हैं:
new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
लेकिन अगर आप 0 (संख्या) और "0" नहीं चाहते हैं (एक स्ट्रिंग के अंदर शून्य), आप कर सकते हैं:
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
Array.apply(null, new Array(5)).map(...)
? कारण बस कर (नया ऐरे (5))। नक्शा (...) युक्ति के रूप में काम नहीं करेगा बताता है
new
) जब आप ऐसा Array(5)
करते हैं तो आप एक ऐसी वस्तु बना रहे हैं जो थोड़े इस तरह दिखती है: { length: 5, __proto__: Array.prototype }
- कोशिश करें console.dir( Array(5) )
। सूचना है कि यह किसी भी गुण नहीं हैं 0
, 1
, 2
, आदि लेकिन जब आप apply
कि पर्यत Array
निर्माता है, यह कह रही है की तरह है Array(undefined, undefined, undefined, undefined, undefined)
। और आपको एक ऑब्जेक्ट मिलता है जो थोड़े जैसा दिखता है { length: 5, 0: undefined, 1: undefined...}
। map
गुण पर काम करता है 0
, 1
आदि है और इसीलिए आपके उदाहरण काम नहीं करता है, लेकिन आप का उपयोग जब apply
यह होता है।
.apply
वास्तव में वही है जो आप चाहते this
हैं। इन उद्देश्यों के लिए this
कोई फर्क नहीं पड़ता है - हम केवल "सुविधा" के फैलने वाले पैरामीटर के बारे में परवाह करते हैं .apply
- इसलिए इसका कोई भी मूल्य हो सकता है। मुझे पसंद है null
क्योंकि यह सस्ता है, आप शायद इसका उपयोग नहीं करना चाहते हैं {}
या []
तब से जब तक आप बिना किसी कारण के किसी वस्तु को तत्काल भेज देंगे।
यहाँ ES6 का उपयोग करने का एक और तरीका है जो किसी ने अब तक उल्लेख नहीं किया है:
> Array.from(Array(3), () => 0)
< [0, 0, 0]
यह दूसरे पैरामीटर के रूप में एक मैप फंक्शन पास करके काम करता है Array.from
।
ऊपर दिए गए उदाहरण में, पहला पैरामीटर मान से भरे 3 पदों की एक सरणी आवंटित करता है undefined
और फिर लंबो फ़ंक्शन फ़ंक्शन उनमें से प्रत्येक को मूल्य पर मैप करता है 0
।
यद्यपि Array(len).fill(0)
यह छोटा है, यह काम नहीं करता है यदि आपको पहले कुछ संगणना करके सरणी को भरने की आवश्यकता है (मुझे पता है कि सवाल इसके लिए नहीं पूछा गया था, लेकिन बहुत से लोग इस की तलाश में यहां समाप्त होते हैं) ।
उदाहरण के लिए, यदि आपको 10 यादृच्छिक संख्याओं के साथ एक सरणी की आवश्यकता है:
> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]
यह समतुल्य से अधिक संक्षिप्त (और सुरुचिपूर्ण) है:
const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
numbers[i] = Math.round(10 * Math.random());
}
इस पद्धति का उपयोग कॉलबैक में दिए गए सूचकांक पैरामीटर का लाभ उठाकर संख्याओं के अनुक्रम उत्पन्न करने के लिए भी किया जा सकता है:
> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
repeat()
चूँकि इस जवाब को अच्छी तरह से ध्यान दिया जा रहा है, मैं भी इस शांत चाल को दिखाना चाहता था। यद्यपि मेरे मुख्य उत्तर के रूप में उपयोगी नहीं है, फिर भी बहुत ज्ञात नहीं, लेकिन बहुत उपयोगी स्ट्रिंग repeat()
पद्धति का परिचय देगा । यहाँ चाल है:
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
शांत हुह? repeat()
एक स्ट्रिंग बनाने के लिए एक बहुत ही उपयोगी विधि है जो मूल स्ट्रिंग की पुनरावृत्ति एक निश्चित संख्या है। उसके बाद, split()
हमारे लिए एक ऐरे बनाता है, जो कि तब map()
हम चाहते हैं कि मूल्यों के लिए है। इसे चरणों में तोड़ना:
> "?".repeat(10)
< "??????????"
> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
repeat
चाल निश्चित रूप से उत्पादन में नहीं चाहता है, Array.from()
पूरी तरह से ठीक है :-)
Array(n).fill(0)
(16 चार), जहां n
सरणी का आकार है
2018.10.28 मैंने अन्य उत्तरों से 15 प्रस्तावों की तुलना की। मैक ओएस एक्स 10.13.6 हाई सिएरा पर तीन ब्राउज़रों पर परीक्षण किया गया: क्रोम 69.0.3497, सफारी 12.0 (13606.2.11) और फ़ायरफ़ॉक्स 63.0 (64 बिट)।
नीचे मैं सबसे तेज़ ब्राउज़र (सफारी) के लिए परिणाम दिखाता हूँ:
सभी ब्राउज़रों के लिए सबसे तेज़ समाधान एम था - हालांकि यह "विशिष्ट सरणी" नहीं है (लेकिन बहुत तेज़ है) - सफारी 33.8k संचालन / दूसरा, क्रोम 5.2k, FF 3.5k,
विशिष्ट सरणियों के लिए सबसे तेज़ समाधान:
सबसे धीमा समाधान:
समाधान एन केवल फ़ायरफ़ॉक्स और क्रोम पर काम करता है।
सबसे तेजी से:
सबसे धीमा:
n
फ़ायरफ़ॉक्स पर छोटा छोड़कर ) एम था let a = new Float32Array(n)
(हालांकि विशिष्ट सरणी नहीं है) - इसके लिए सबसे तेज़ ब्राउज़र सफारी था (बड़े के लिए)n
> क्रोम की तुलना में 6 गुना तेज,> फ़ायरफ़ॉक्स की तुलना में 9 गुना तेज़)let a = Array(n).fill(0)
(तेज और लघु कोड) है आप यहां अपनी मशीन पर परीक्षण कर सकते हैं ।
let a=[]; for(i=n;i--;) a.push(0);
- लेकिन यह 4x से धीमा है fill(0)
- इसलिए मैं उस मामले में चित्र चुड़ैल को भी अपडेट नहीं करूंगा।
a = new Array(n); for (let i = 0; i < n; ++i) a[i] = 0;
। टेस्ट
पहले से ही वर्णित ईएस 6 भरण विधि इस बात का ध्यान रखता है। अधिकांश आधुनिक डेस्कटॉप ब्राउज़र पहले से ही आज (क्रोमियम, एफएफ, एज और सफारी) [ 1 ] के रूप में आवश्यक ऐरे प्रोटोटाइप तरीकों का समर्थन करते हैं । आप MDN पर विवरण देख सकते हैं । एक सरल उपयोग उदाहरण है
a = new Array(10).fill(0);
वर्तमान ब्राउज़र समर्थन को देखते हुए आपको इसका उपयोग करने के लिए सतर्क रहना चाहिए जब तक कि आप सुनिश्चित न हों कि आपके दर्शक आधुनिक डेस्कटॉप ब्राउज़र का उपयोग करते हैं।
a = Array(10).fill(null).map(() => { return []; });
a = Array(10).fill(0).map( _ => [] );
नोट अगस्त 2013 को जोड़ा गया, फरवरी 2015 को अपडेट किया गया: 2009 से नीचे का उत्तर जावास्क्रिप्ट के सामान्य Array
प्रकार से संबंधित है । यह ES2015 में परिभाषित नए टाइप किए गए सरणियों से संबंधित नहीं है [और अब कई ब्राउज़रों में उपलब्ध है], जैसे Int32Array
और ऐसे। यह भी ध्यान दें कि ES2015 Arrays और टाइप किए गए सरणियोंfill
दोनों के लिए एक विधि जोड़ता है , जो आपको भरने के लिए सबसे कुशल तरीका होने की संभावना है ...
इसके अलावा, यह कुछ कार्यान्वयन के लिए एक बड़ा अंतर बना सकता है कि आप सरणी कैसे बनाते हैं। क्रोम का V8 इंजन, विशेष रूप से, अत्यधिक कुशल, अस्पष्ट-मेमोरी सरणी का उपयोग करने की कोशिश करता है, अगर यह सोचता है कि यह आवश्यक होने पर ही ऑब्जेक्ट-आधारित सरणी में स्थानांतरित हो सकता है।
अधिकांश भाषाओं के साथ, यह पूर्व-आबंटित होगा, फिर इस तरह शून्य-भरण:
function newFilledArray(len, val) {
var rv = new Array(len);
while (--len >= 0) {
rv[len] = val;
}
return rv;
}
लेकिन , जावास्क्रिप्ट सरणियाँ वास्तव में सरणियाँ नहीं हैं , वे अन्य सभी जावास्क्रिप्ट वस्तुओं की तरह ही कुंजी / मान मानचित्र हैं, इसलिए ऐसा करने के लिए कोई "पूर्व-आबंटित" नहीं है (लंबाई सेट करने के लिए आवंटित नहीं है कि भरने के लिए कई स्लॉट), न ही क्या यह मानने का कोई कारण है कि शून्य से नीचे की गणना करने का लाभ (जो कि लूप में तुलना करने के लिए बस तेज है) को रिवर्स ऑर्डर में कुंजियों को जोड़कर आगे नहीं बढ़ाया जाता है जब कार्यान्वयन अच्छी तरह से कुंजी की हैंडलिंग को अनुकूलित कर सकता है। सिद्धांत पर सरणियों से संबंधित आप आमतौर पर उन्हें क्रम में करेंगे।
वास्तव में, मैथ्यू क्रुमली ने बताया कि नीचे की गिनती की तुलना में फ़ायरफ़ॉक्स पर गिनती धीमी है, जिसके परिणामस्वरूप मैं पुष्टि कर सकता हूं - यह इसका सरणी भाग है (शून्य तक लूपिंग अभी भी एक संस्करण में एक सीमा तक लूपिंग की तुलना में तेज़ है)। जाहिरा तौर पर तत्वों को रिवर्स ऑर्डर में सरणी में जोड़ना फ़ायरफ़ॉक्स पर धीमी गति से ऑप है। वास्तव में, जावास्क्रिप्ट कार्यान्वयन द्वारा परिणाम काफी भिन्न होते हैं (जो कि आश्चर्य की बात नहीं है)। ब्राउज़र कार्यान्वयन के लिए एक त्वरित और गंदा परीक्षण पृष्ठ (नीचे), बहुत गंदा है, परीक्षणों के दौरान उपज नहीं देता है, इसलिए न्यूनतम प्रतिक्रिया प्रदान करता है और स्क्रिप्ट समय सीमा से दूर चलेगा)। मैं परीक्षणों के बीच ताज़ा करने की सलाह देता हूं; यदि आप नहीं करते हैं तो एफएफ (कम से कम) दोहराया परीक्षणों पर धीमा हो जाता है।
काफी जटिल संस्करण जो Array # concat का उपयोग करता है, FF पर सीधे init से 1,000 और 2,000 तत्व सरणियों के बीच कहीं अधिक तेज़ है। क्रोम के V8 इंजन पर, हालांकि, हर बार सीधा इनिट बाहर जीत जाता है ...
यहाँ परीक्षण पृष्ठ ( लाइव कॉपी ) है:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Zero Init Test Page</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
#log p {
margin: 0;
padding: 0;
}
.error {
color: red;
}
.winner {
color: green;
font-weight: bold;
}
</style>
<script type='text/javascript' src='prototype-1.6.0.3.js'></script>
<script type='text/javascript'>
var testdefs = {
'downpre': {
total: 0,
desc: "Count down, pre-decrement",
func: makeWithCountDownPre
},
'downpost': {
total: 0,
desc: "Count down, post-decrement",
func: makeWithCountDownPost
},
'up': {
total: 0,
desc: "Count up (normal)",
func: makeWithCountUp
},
'downandup': {
total: 0,
desc: "Count down (for loop) and up (for filling)",
func: makeWithCountDownArrayUp
},
'concat': {
total: 0,
desc: "Concat",
func: makeWithConcat
}
};
document.observe('dom:loaded', function() {
var markup, defname;
markup = "";
for (defname in testdefs) {
markup +=
"<div><input type='checkbox' id='chk_" + defname + "' checked>" +
"<label for='chk_" + defname + "'>" + testdefs[defname].desc + "</label></div>";
}
$('checkboxes').update(markup);
$('btnTest').observe('click', btnTestClick);
});
function epoch() {
return (new Date()).getTime();
}
function btnTestClick() {
// Clear log
$('log').update('Testing...');
// Show running
$('btnTest').disabled = true;
// Run after a pause while the browser updates display
btnTestClickPart2.defer();
}
function btnTestClickPart2() {
try {
runTests();
}
catch (e) {
log("Exception: " + e);
}
// Re-enable the button; we don't yheidl
$('btnTest').disabled = false;
}
function runTests() {
var start, time, counter, length, defname, def, results, a, invalid, lowest, s;
// Get loops and length
s = $F('txtLoops');
runcount = parseInt(s);
if (isNaN(runcount) || runcount <= 0) {
log("Invalid loops value '" + s + "'");
return;
}
s = $F('txtLength');
length = parseInt(s);
if (isNaN(length) || length <= 0) {
log("Invalid length value '" + s + "'");
return;
}
// Clear log
$('log').update('');
// Do it
for (counter = 0; counter <= runcount; ++counter) {
for (defname in testdefs) {
def = testdefs[defname];
if ($('chk_' + defname).checked) {
start = epoch();
a = def.func(length);
time = epoch() - start;
if (counter == 0) {
// Don't count (warm up), but do check the algorithm works
invalid = validateResult(a, length);
if (invalid) {
log("<span class='error'>FAILURE</span> with def " + defname + ": " + invalid);
return;
}
}
else {
// Count this one
log("#" + counter + ": " + def.desc + ": " + time + "ms");
def.total += time;
}
}
}
}
for (defname in testdefs) {
def = testdefs[defname];
if ($('chk_' + defname).checked) {
def.avg = def.total / runcount;
if (typeof lowest != 'number' || lowest > def.avg) {
lowest = def.avg;
}
}
}
results =
"<p>Results:" +
"<br>Length: " + length +
"<br>Loops: " + runcount +
"</p>";
for (defname in testdefs) {
def = testdefs[defname];
if ($('chk_' + defname).checked) {
results += "<p" + (lowest == def.avg ? " class='winner'" : "") + ">" + def.desc + ", average time: " + def.avg + "ms</p>";
}
}
results += "<hr>";
$('log').insert({top: results});
}
function validateResult(a, length) {
var n;
if (a.length != length) {
return "Length is wrong";
}
for (n = length - 1; n >= 0; --n) {
if (a[n] != 0) {
return "Index " + n + " is not zero";
}
}
return undefined;
}
function makeWithCountDownPre(len) {
var a;
a = new Array(len);
while (--len >= 0) {
a[len] = 0;
}
return a;
}
function makeWithCountDownPost(len) {
var a;
a = new Array(len);
while (len-- > 0) {
a[len] = 0;
}
return a;
}
function makeWithCountUp(len) {
var a, i;
a = new Array(len);
for (i = 0; i < len; ++i) {
a[i] = 0;
}
return a;
}
function makeWithCountDownArrayUp(len) {
var a, i;
a = new Array(len);
i = 0;
while (--len >= 0) {
a[i++] = 0;
}
return a;
}
function makeWithConcat(len) {
var a, rem, currlen;
if (len == 0) {
return [];
}
a = [0];
currlen = 1;
while (currlen < len) {
rem = len - currlen;
if (rem < currlen) {
a = a.concat(a.slice(0, rem));
}
else {
a = a.concat(a);
}
currlen = a.length;
}
return a;
}
function log(msg) {
$('log').appendChild(new Element('p').update(msg));
}
</script>
</head>
<body><div>
<label for='txtLength'>Length:</label><input type='text' id='txtLength' value='10000'>
<br><label for='txtLoops'>Loops:</label><input type='text' id='txtLoops' value='10'>
<div id='checkboxes'></div>
<br><input type='button' id='btnTest' value='Test'>
<hr>
<div id='log'></div>
</div></body>
</html>
डिफ़ॉल्ट रूप से Uint8Array
, Uint16Array
और Uint32Array
कक्षाएं शून्य को अपने मान के रूप में रखती हैं, इसलिए आपको किसी भी जटिल भरने की तकनीक की आवश्यकता नहीं है, बस करें:
var ary = new Uint8Array(10);
सरणी के सभी तत्व ary
डिफ़ॉल्ट रूप से शून्य होंगे।
Array.isArray(ary)
लिए false
। लंबाई भी केवल पढ़ने के लिए है ताकि आप इसके साथ नई वस्तुओं को आगे न बढ़ा ary.push
0
को उनके डिफ़ॉल्ट मान के रूप में रखें ।
Array.from(new Uint8Array(10))
एक सामान्य सरणी प्रदान करेगा।
Array(n).fill(0)
क्रोम की तुलना में लगभग 5 गुना धीमा है अगर आपको वास्तव में एक जेएस एरे की जरूरत है। यदि आप एक TypedArray का उपयोग कर सकते हैं, तो यह तुलना में बहुत तेज़ है .fill(0)
, हालाँकि, विशेष रूप से यदि आप के डिफ़ॉल्ट आरंभीकरण मूल्य का उपयोग कर सकते हैं 0
। ऐसा लगता नहीं है कि एक निर्माता को भरने-मूल्य और लंबाई लगती है, जिस तरह से सी ++ के std::vector
पास है। यह किसी भी गैर-शून्य मान के लिए लगता है कि आपको एक शून्य टाइप्डएरे का निर्माण करना है और फिर उसे भरना है। : /
यदि आप ES6 का उपयोग करते हैं, तो आप Array.from () का उपयोग कर सकते हैं :
Array.from({ length: 3 }, () => 0);
//[0, 0, 0]
के रूप में एक ही परिणाम है
Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]
चूंकि
Array.from({ length: 3 })
//[undefined, undefined, undefined]
function makeArrayOf(value, length) {
var arr = [], i = length;
while (i--) {
arr[i] = value;
}
return arr;
}
makeArrayOf(0, 5); // [0, 0, 0, 0, 0]
makeArrayOf('x', 3); // ['x', 'x', 'x']
ध्यान दें कि while
आमतौर पर तुलना में अधिक कुशल है for-in
, forEach
आदि
i
स्थानीय चर विलुप्त नहीं है? length
मूल्य से पारित कर दिया है ताकि आप इसे सीधे गिरावट में सक्षम होना चाहिए।
arr[i] = value
) में एक मनमाना बिंदु पर मूल्यों को असाइन करने के लिए बहुत धीमा है । यह शुरू से अंत तक और उपयोग करने के लिए लूप के लिए बहुत तेज़ है arr.push(value)
। यह कष्टप्रद है, क्योंकि मुझे आपकी विधि पसंद है।
ऑब्जेक्ट नोटेशन का उपयोग करना
var x = [];
शून्य भरा? पसंद...
var x = [0,0,0,0,0,0];
'अपरिभाषित' से भरा ...
var x = new Array(7);
शून्य के साथ obj संकेतन
var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;
एक साइड नोट के रूप में, यदि आप ऐरे के प्रोटोटाइप को संशोधित करते हैं, तो दोनों
var x = new Array();
तथा
var y = [];
उन प्रोटोटाइप संशोधनों होगा
किसी भी दर पर, मैं इस ऑपरेशन की दक्षता या गति के बारे में अधिक चिंतित नहीं होगा, बहुत सारी अन्य चीजें हैं जो आप संभवतः कर रहे हैं जो शून्य से अधिक की मनमानी लंबाई की एक सरणी को स्थापित करने की तुलना में कहीं अधिक बेकार और महंगी हैं।
null
इस सरणी में कोई s नहीं हैं -var x = new Array(7);
new Array(7)
करता नहीं एक सरणी "अपरिभाषित से भरा" पैदा करते हैं। यह लंबाई के साथ एक खाली सरणी बनाता है 7.
(new Array(10)).fill(0)
।
मैंने पूर्व-आवंटन / पूर्व-आवंटन के सभी संयोजनों का परीक्षण किया है, IE 6/7/8, फ़ायरफ़ॉक्स 3.5, क्रोम, और ओपेरा में छोरों के लिए / नीचे की गिनती करते हुए / के लिए / पूर्व-आवंटन नहीं किया है।
नीचे दिए गए फ़ंक्शंस फ़ायरफ़ॉक्स, क्रोम, और IE8 में लगातार सबसे तेज़ या बेहद नज़दीकी थे, और ओपेरा और आईई 6 में सबसे तेज़ से ज्यादा धीमा नहीं था। यह मेरी राय में सबसे सरल और स्पष्ट भी है। मुझे कई ब्राउज़र मिले हैं जहाँ लूप संस्करण थोड़ा तेज़ है, इसलिए मैं इसे संदर्भ के लिए भी शामिल कर रहा हूँ।
function newFilledArray(length, val) {
var array = [];
for (var i = 0; i < length; i++) {
array[i] = val;
}
return array;
}
या
function newFilledArray(length, val) {
var array = [];
var i = 0;
while (i < length) {
array[i++] = val;
}
return array;
}
var array = []
घोषणा को वास्तव में लूप के पहले भाग में फेंक सकते हैं , केवल एक अल्पविराम द्वारा अलग किया गया है।
length
पहले से दिए गए मान के लिए सरणी की लंबाई निर्धारित करें ताकि यह लगातार बदल न जाए। मेरी मशीन पर शून्य से 40 मिलियन से 8 तक की 1 मिलियन लंबाई की सरणी लाया।
for (i = 0, array = []; i < length; ++i) array[i] = val;
.. बहुत कम ब्लॉक? ... किसी भी तरह, ... अगर मैं array.length
लंबाई के लिए नई सरणी सेट करता हूं .. तो मुझे लगता है कि एफएफ में एक और 10% -15% की गति वृद्धि हुई है ... क्रोम में, यह गति को दोगुना करने के लिए लगता है -> var i, array = []; array.length = length; while(i < length) array[i++] = val;
(अभी भी तेज था अगर मैंने इसे एक for
लूप के रूप में छोड़ दिया ... लेकिन while
यदि आपको अपने कोड के निष्पादन के दौरान विभिन्न लंबाई के कई शून्य भरे हुए सरणियों को बनाने की आवश्यकता है, तो मैंने इसे प्राप्त करने का सबसे तेज़ तरीका एक बार शून्य सरणी बनाना है। , इस विषय पर बताए गए तरीकों में से एक का उपयोग करके, लंबाई जो आपको पता है कि कभी भी पार नहीं किया जाएगा, और फिर उस सरणी को आवश्यक रूप से टुकड़ा करें।
उदाहरण के लिए (सरणी को इनिशियलाइज़ करने के लिए ऊपर दिए गए उत्तर से फ़ंक्शन का उपयोग करके), अधिकतम लंबाई का एक शून्य भरा हुआ सरणी बनाएँ , कोड के लिए दृश्यमान चर के रूप में जिसे शून्य सरणियों की आवश्यकता होती है:
var zero = newFilledArray(maxLength, 0);
अब इस एरे को हर बार स्लाइस करें, इसके लिए आपको आवश्यक लम्बाई के एक शून्य भरे हुए एलीवेटर की आवश्यकता है < maxLength :
zero.slice(0, requiredLength);
मैं अपने कोड के निष्पादन के दौरान हजारों बार शून्य भरे हुए सरणियों का निर्माण कर रहा था, इससे प्रक्रिया में काफी तेजी आई।
मेरे पास नापसंद करने का कोश्ई कारण नहीं है:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);
Zertosh द्वारा सुझाव दिया गया है, लेकिन एक नए ES6 सरणी एक्सटेंशन में आप इसे मूल रूप से fill
विधि के साथ कर सकते हैं । अब IE एज, क्रोम और एफएफ इसका समर्थन करते हैं, लेकिन संगतता तालिका की जांच करें
new Array(3).fill(0)
आपको दे देंगे [0, 0, 0]
। आप किसी भी मान new Array(5).fill('abc')
( जैसे ऑब्जेक्ट और अन्य सरणियों) के साथ सरणी को भर सकते हैं ।
उसके शीर्ष पर आप पिछली सरणियों को भरने के साथ संशोधित कर सकते हैं:
arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5) # what to fill, start, end
जो आपको देता है: [1, 2, 3, 9, 9, 6]
जिस तरह से मैं आमतौर पर यह करता हूं (और आश्चर्यजनक तेज है) का उपयोग कर रहा है Uint8Array
। उदाहरण के लिए, 1M तत्वों का शून्य भरा वेक्टर बनाना:
var zeroFilled = [].slice.apply(new Uint8Array(1000000))
मैं एक लिनक्स उपयोगकर्ता हूं और हमेशा मेरे लिए काम किया है, लेकिन एक बार मैक का उपयोग करने वाले एक दोस्त के पास कुछ गैर-शून्य तत्व थे। मैंने सोचा कि उसकी मशीन खराब थी, लेकिन फिर भी यहाँ सबसे सुरक्षित तरीका है जिसे हमने ठीक किया है:
var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000))
संपादित
क्रोम 25.0.1364.160
फ़ायरफ़ॉक्स 20.0
सबसे महत्वपूर्ण परीक्षण (मेरे लिए कम से कम) गुम: नोड एक। मुझे शक है कि यह क्रोम बेंचमार्क के करीब है।
लॉश या अंडरस्कोर का उपयोग करना
_.range(0, length - 1, 0);
या यदि आपके पास एक सरणी मौजूद है और आप उसी लंबाई की एक सरणी चाहते हैं
array.map(_.constant(0));
_.range(0, length, 0)
, मुझे विश्वास है। लोदश अंतिम मूल्य का अनन्य है
के रूप में ECMAScript2016 , वहाँ बड़े सरणियों के लिए एक स्पष्ट विकल्प है।
चूँकि यह उत्तर अभी भी Google खोजों पर शीर्ष के पास दिखाई देता है, यहाँ 2017 के लिए एक उत्तर है।
इस प्रश्न पर अब तक प्रस्तावित कई दर्जन लोकप्रिय तरीकों के साथ एक वर्तमान jsbench है , जिसमें कई प्रस्तावित हैं। यदि आप एक बेहतर तरीका ढूंढते हैं तो कृपया जोड़ें, कांटा और साझा करें।
मैं यह नोट करना चाहता हूं कि एक मनमाना लंबाई शून्य भरा सरणी बनाने का कोई सच्चा सबसे कुशल तरीका नहीं है। आप गति, या स्पष्टता और स्थिरता के लिए अनुकूलन कर सकते हैं - या तो परियोजना की जरूरतों के आधार पर अधिक कुशल विकल्प माना जा सकता है।
गति के लिए अनुकूलन करते समय, आप चाहते हैं: शाब्दिक सिंटैक्स का उपयोग करके सरणी बनाएं; लंबाई सेट करें, पुनरावृति चर को इनिशियलाइज़ करें, और थोड़ी देर लूप का उपयोग करके सरणी के माध्यम से पुनरावृति करें। यहाँ एक उदाहरण है।
const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
arr[i] = 0;
i++;
}
एक और संभावित कार्यान्वयन होगा:
(arr = []).length = n;
let i = 0;
while (i < n) {
arr[i] = 0;
i++;
}
लेकिन मैं दृढ़ता से इस दूसरे आरोपण का उपयोग कर हतोत्साहित करता हूं क्योंकि यह कम स्पष्ट है और आपको अपने सरणी चर पर ब्लॉक स्कूपिंग को बनाए रखने की अनुमति नहीं देता है।
लूप के लिए भरने की तुलना में ये काफी तेज हैं, और मानक विधि की तुलना में लगभग 90% तेज है
const arr = Array(n).fill(0);
लेकिन यह भरने की विधि अभी भी स्पष्टता, संक्षिप्तता और स्थिरता के कारण छोटे सरणियों के लिए सबसे कुशल विकल्प है। जब तक आप हजारों या अधिक के क्रम पर लम्बाई के साथ बहुत सारे सरणियाँ नहीं बना लेते, प्रदर्शन अंतर संभवत: आपको नहीं मारेंगे।
कुछ अन्य महत्वपूर्ण नोट। अधिकांश स्टाइल गाइड आपको सलाह देते हैं var
कि ES6 या बाद में उपयोग करते समय आप किसी विशेष कारण के बिना उपयोग न करें । const
उन चरों का उपयोग करें जिन्हें पुनर्परिभाषित नहीं किया जाएगा और जो चरों के लिए उपयोग किया let
जाएगा। MDN और Airbnb की स्टाइल गाइड महान सर्वोत्तम प्रथाओं पर अधिक जानकारी के लिए जाने के लिए हैं। प्रश्न वाक्यविन्यास के बारे में नहीं था, लेकिन यह महत्वपूर्ण है कि पुराने और नए उत्तरों के इन स्थानों के माध्यम से खोज करने पर JS के नए लोग इन नए मानकों के बारे में जानते हैं।
एक नया ऐरे बनाने के लिए
new Array(arrayLength).fill(0);
किसी मौजूदा ऐरे के अंत में कुछ मान जोड़ने के लिए
[...existingArray, ...new Array(numberOfElementsToAdd).fill(0)]
//**To create an all new Array**
console.log(new Array(5).fill(0));
//**To add some values at the end of an existing Array**
let existingArray = [1,2,3]
console.log([...existingArray, ...new Array(5).fill(0)]);
इस विधि को उत्तरों में नहीं देखा, इसलिए यहाँ यह है:
"0".repeat( 200 ).split("").map( parseFloat )
परिणाम में आपको लंबाई 200 की शून्य-मूल्यवान सरणी मिलेगी:
[ 0, 0, 0, 0, ... 0 ]
मैं इस कोड के प्रदर्शन के बारे में निश्चित नहीं हूं, लेकिन अगर आप इसे अपेक्षाकृत छोटे सरणियों के लिए उपयोग करते हैं तो यह एक मुद्दा नहीं होना चाहिए।
const arr = Array.from({ length: 10 }).fill(0)
concat
Chrome (2013-03-21) पर मेरे परीक्षणों में यह संस्करण बहुत तेज़ है। सीधे init के लिए लगभग 200ms 10,000,000 तत्वों बनाम 675 के लिए।
function filledArray(len, value) {
if (len <= 0) return [];
var result = [value];
while (result.length < len/2) {
result = result.concat(result);
}
return result.concat(result.slice(0, len-result.length));
}
बोनस: यदि आप स्ट्रिंग्स के साथ अपने एरे को भरना चाहते हैं, तो यह एक संक्षिप्त तरीका है इसे करने के लिए ( concat
हालांकि उतना तेज़ नहीं है ):
function filledArrayString(len, value) {
return new Array(len+1).join(value).split('');
}
मैं टीजे क्राउडर द्वारा दिए गए शानदार जवाब का परीक्षण कर रहा था, और क्रोम में उनके परीक्षणों में किसी भी आउटपरफॉर्म करने वाले कॉनकैट समाधान पर आधारित एक पुनरावर्ती मर्ज के साथ आया था (मैंने अन्य ब्राउज़रों का परीक्षण नहीं किया था)।
function makeRec(len, acc) {
if (acc == null) acc = [];
if (len <= 1) return acc;
var b = makeRec(len >> 1, [0]);
b = b.concat(b);
if (len & 1) b = b.concat([0]);
return b;
},
के साथ विधि को बुलाओ makeRec(29)
।
यह इंगित करने के लायक हो सकता है, जिसे ECMAScript 6 (हार्मनी) के प्रस्ताव केArray.prototype.fill
हिस्से के रूप में जोड़ा गया था । मैं थ्रेड पर उल्लिखित अन्य विकल्पों पर विचार करने से पहले, नीचे लिखे पॉलीफ़िल के साथ जाना चाहूंगा।
if (!Array.prototype.fill) {
Array.prototype.fill = function(value) {
// Steps 1-2.
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
// Steps 3-5.
var len = O.length >>> 0;
// Steps 6-7.
var start = arguments[1];
var relativeStart = start >> 0;
// Step 8.
var k = relativeStart < 0 ?
Math.max(len + relativeStart, 0) :
Math.min(relativeStart, len);
// Steps 9-10.
var end = arguments[2];
var relativeEnd = end === undefined ?
len : end >> 0;
// Step 11.
var final = relativeEnd < 0 ?
Math.max(len + relativeEnd, 0) :
Math.min(relativeEnd, len);
// Step 12.
while (k < final) {
O[k] = value;
k++;
}
// Step 13.
return O;
};
}
लूप कोड के लिए सबसे छोटा
a=i=[];for(;i<100;)a[i++]=0;
edit:
for(a=i=[];i<100;)a[i++]=0;
or
for(a=[],i=100;i--;)a[i]=0;
सुरक्षित संस्करण संस्करण
var a=[],i=0;for(;i<100;)a[i++]=0;
edit:
for(var i=100,a=[];i--;)a[i]=0;
n
यह कम होगा:for(var a=[];n--;a[n]=0);
let filled = [];
filled.length = 10;
filled.fill(0);
console.log(filled);
मेरा सबसे तेज़ कार्य होगा:
function newFilledArray(len, val) {
var a = [];
while(len--){
a.push(val);
}
return a;
}
var st = (new Date()).getTime();
newFilledArray(1000000, 0)
console.log((new Date()).getTime() - st); // returned 63, 65, 62 milliseconds
सरणी को घोषित करने और प्रत्येक आइटम को संदर्भित करने की तुलना में सरणी में आइटम जोड़ने के लिए देशी पुश और शिफ्ट का उपयोग सरणी में बहुत तेज (लगभग 10 गुना) है।
fyi: मैं लगातार पहले लूप के साथ तेज समय प्राप्त करता हूं, जो नीचे गिन रहा है, जब यह फायरबग (फ़ायरफ़ॉक्स एक्सटेंशन) में चल रहा है।
var a = [];
var len = 1000000;
var st = (new Date()).getTime();
while(len){
a.push(0);
len -= 1;
}
console.log((new Date()).getTime() - st); // returned 863, 894, 875 milliseconds
st = (new Date()).getTime();
len = 1000000;
a = [];
for(var i = 0; i < len; i++){
a.push(0);
}
console.log((new Date()).getTime() - st); // returned 1155, 1179, 1163 milliseconds
मुझे यह जानने में दिलचस्पी है कि टीजे क्राउडर क्या बनाता है? :-)
while (len--)
.. मेरी प्रोसेसिंग का समय लगभग 60ms से लेकर 54ms तक हो गया है
मुझे पता था कि मेरा यह प्रोटॉइड होगा कहीं :)
Array.prototype.init = function(x,n)
{
if(typeof(n)=='undefined') { n = this.length; }
while (n--) { this[n] = x; }
return this;
}
var a = (new Array(5)).init(0);
var b = [].init(0,4);
संपादित करें: परीक्षण
जोशुआ और अन्य तरीकों के जवाब में मैंने अपना स्वयं का बेंचमार्किंग किया, और मैं उन रिपोर्ट के लिए पूरी तरह से अलग परिणाम देख रहा हूं।
यहाँ मैंने क्या परीक्षण किया है:
//my original method
Array.prototype.init = function(x,n)
{
if(typeof(n)=='undefined') { n = this.length; }
while (n--) { this[n] = x; }
return this;
}
//now using push which I had previously thought to be slower than direct assignment
Array.prototype.init2 = function(x,n)
{
if(typeof(n)=='undefined') { n = this.length; }
while (n--) { this.push(x); }
return this;
}
//joshua's method
function newFilledArray(len, val) {
var a = [];
while(len--){
a.push(val);
}
return a;
}
//test m1 and m2 with short arrays many times 10K * 10
var a = new Date();
for(var i=0; i<10000; i++)
{
var t1 = [].init(0,10);
}
var A = new Date();
var b = new Date();
for(var i=0; i<10000; i++)
{
var t2 = [].init2(0,10);
}
var B = new Date();
//test m1 and m2 with long array created once 100K
var c = new Date();
var t3 = [].init(0,100000);
var C = new Date();
var d = new Date();
var t4 = [].init2(0,100000);
var D = new Date();
//test m3 with short array many times 10K * 10
var e = new Date();
for(var i=0; i<10000; i++)
{
var t5 = newFilledArray(10,0);
}
var E = new Date();
//test m3 with long array created once 100K
var f = new Date();
var t6 = newFilledArray(100000, 0)
var F = new Date();
परिणाम:
IE7 deltas:
dA=156
dB=359
dC=125
dD=375
dE=468
dF=412
FF3.5 deltas:
dA=6
dB=13
dC=63
dD=8
dE=12
dF=8
तो मेरे रेकिंग पुश से वास्तव में धीमी गति से होता है, लेकिन एफएफ में लंबे समय तक सरणियों के साथ बेहतर प्रदर्शन करता है लेकिन आईई में इससे भी बदतर होता है जो सामान्य रूप से बेकार होता है (क्वेल आश्चर्य)।
b = []...
) पहले की तुलना में 10-15% तेज है, लेकिन यह यहोशू के उत्तर की तुलना में 10 गुना अधिक धीमी है।
else {this.length=n;}
बाद शामिल करें this.length
। यदि आवश्यक हो तो init
इसे पहले से मौजूद सरणी को छोटा कर दिया जाएगा, जब इसे अलग लंबाई में पुन: लागू किया जाएगा n
।
अनाम फ़ंक्शन:
(function(n) { while(n-- && this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]
लूप के साथ थोड़ा छोटा:
(function(n) { for(;n--;this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]
किसी भी के साथ काम करता है Object
, बस अंदर क्या है बदल जाते हैं this.push()
।
आप फ़ंक्शन को भी सहेज सकते हैं:
function fill(size, content) {
for(;size--;this.push(content));
return this;
}
इसका उपयोग करके कॉल करें:
var helloArray = fill.call([], 5, 'hello');
// => ['hello', 'hello', 'hello', 'hello', 'hello']
पहले से मौजूद सरणी में तत्वों को जोड़ना:
var helloWorldArray = fill.call(helloArray, 5, 'world');
// => ['hello', 'hello', 'hello', 'hello', 'hello', 'world', 'world', 'world', 'world', 'world']