ค้นหาเว็บไซต์

วิธีที่มีประสิทธิภาพที่สุดในการสร้างอาเรย์ JavaScript ที่เต็มไปด้วยศูนย์?


วิธีที่มีประสิทธิภาพที่สุดในการสร้างอาร์เรย์ที่เต็มไปด้วยศูนย์และมีความยาวตามต้องการใน JavaScript คืออะไร?

คำตอบ #1

ES6 แนะนำ Array.prototype.fill สามารถใช้ได้ดังนี้:

new Array(len).fill(0);

ไม่แน่ใจว่ามันเร็วหรือเปล่า แต่ฉันชอบเพราะมันสั้นและบรรยายตัวเองได้

มันยังไม่ได้อยู่ใน IE (ตรวจสอบความเข้ากันได้) แต่มีโพลีฟิลล์ให้ใช้งานอยู่

คำตอบ #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]

คำตอบ #3

โดยย่อ

วิธีแก้ปัญหาที่เร็วที่สุด:

let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;

วิธีแก้ปัญหาที่สั้นที่สุด (สะดวก) (ช้ากว่า 3 เท่าสำหรับอาร์เรย์ขนาดเล็ก, ช้ากว่านิดหน่อยสำหรับอาร์เรย์ขนาดใหญ่ (ช้าที่สุดใน Firefox))

Array(n).fill(0)

รายละเอียด

วันนี้ 2020.06.09 ฉันทำการทดสอบบน macOS High Sierra 10.13.6 บนเบราว์เซอร์ Chrome 83.0, Firefox 77.0, และ Safari 13.1 ฉันทดสอบโซลูชันที่เลือกสำหรับสองกรณีทดสอบ

  • อาเรย์ขนาดเล็ก - มี 10 องค์ประกอบ - คุณสามารถทดสอบได้ที่นี่
  • อาเรย์ขนาดใหญ่ - มี 1 ล้านสมาชิก - คุณสามารถทดสอบที่นี่

ข้อสรุป

  • วิธีแก้ปัญหาที่อิงตาม new Array(n)+for (N) เป็นวิธีแก้ปัญหาที่เร็วที่สุดสำหรับอาร์เรย์ขนาดเล็กและอาร์เรย์ขนาดใหญ่ (ยกเว้น Chrome แต่ก็ยังเร็วมากที่นั่น) และแนะนำให้ใช้เป็นวิธีแก้ปัญหาข้ามเบราว์เซอร์ที่เร็ว
  • วิธีแก้ปัญหาที่อิงตาม new Float32Array(n) (I) จะส่งกลับอาเรย์ที่ไม่ปกติ (เช่น คุณไม่สามารถเรียกใช้ push(..) กับมันได้) ดังนั้นฉันจึงไม่เปรียบเทียบผลลัพธ์กับวิธีแก้ปัญหาอื่น ๆ - อย่างไรก็ตาม วิธีแก้ปัญหานี้เร็วกว่าวิธีแก้ปัญหาอื่นประมาณ 10-20 เท่าสำหรับอาเรย์ขนาดใหญ่ในทุกเบราว์เซอร์
  • โซลูชันที่อิงตาม for (L,M,N,O) มีความเร็วสำหรับอาร์เรย์ขนาดเล็ก
  • โซลูชันที่อิงกับ fill (B,C) ทำงานได้เร็วบน Chrome และ Safari แต่กลับช้าที่สุดอย่างน่าประหลาดใจบน Firefox สำหรับอาร์เรย์ขนาดใหญ่ สำหรับอาร์เรย์ขนาดเล็กจะทำงานได้ค่อนข้างเร็วปานกลาง
  • วิธีแก้ปัญหาที่อิงตาม Array.apply (P) จะเกิดข้อผิดพลาดสำหรับอาร์เรย์ขนาดใหญ่

    function P(n) {
      return Array.apply(null, Array(n)).map(Number.prototype.valueOf,0);
    }
    
    try {
      P(1000000);
    } catch(e) { 
      console.error(e.message);
    }

โค้ดและตัวอย่าง

โค้ดด้านล่างแสดงวิธีแก้ปัญหาที่ใช้ในการวัด

function A(n) {
  return [...new Array(n)].fill(0);
}

function B(n) {
  return new Array(n).fill(0);
}

function C(n) {
  return Array(n).fill(0);
}

function D(n) {
  return Array.from({length: n}, () => 0);
}

function E(n) {
  return [...new Array(n)].map(x => 0);
}

// arrays with type

function F(n) {
  return Array.from(new Int32Array(n));
}

function G(n) {
  return Array.from(new Float32Array(n));
}

function H(n) {
  return Array.from(new Float64Array(n)); // needs 2x more memory than float32
}

function I(n) {
  return new Float32Array(n); // this is not typical array
}

function J(n) {
  return [].slice.apply(new Float32Array(n));
}

// Based on for

function K(n) {
  let a = [];
  a.length = n;
  let i = 0;
  while (i < n) {
    a[i] = 0;
    i++;
  }
  return a;
}

function L(n) {
  let a=[]; for(let i=0; i<n; i++) a[i]=0;
  return a;
}

function M(n) {
  let a=[]; for(let i=0; i<n; i++) a.push(0);
  return a;
}

function N(n) {
  let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;
  return a;
}

function O(n) {
  let a = new Array(n); for (let i=n; i--;) a[i] = 0;
  return a;
}

// other

function P(n) {
  return Array.apply(null, Array(n)).map(Number.prototype.valueOf,0);
}

function Q(n) {
  return "0".repeat( n ).split("").map( parseFloat );
}

function R(n) {
  return new Array(n+1).join('0').split('').map(parseFloat)
}

// ---------
// TEST
// ---------
[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R].forEach(f => {
  let a = f(10); 
  console.log(`${f.name} length=${a.length}, arr[0]=${a[0]}, arr[9]=${a[9]}`)
});
This snippets only present used codes

ตัวอย่างผลลัพธ์สำหรับ Chrome:

คำตอบ #4

วิธีที่สง่างามในการเติมอาร์เรย์ด้วยค่าที่คำนวณล่วงหน้า

นี่คือวิธีอีกวิธีหนึ่งในการทำด้วย 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());
}

วิธีนี้ยังสามารถใช้สร้างลำดับของตัวเลขได้โดยใช้ประโยชน์จากพารามิเตอร์ดัชนีที่ให้มาในฟังก์ชัน callback:

> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

คำตอบพิเศษ: เติมอาเรย์โดยใช้ String repeat()

เนื่องจากคำตอบนี้ได้รับความสนใจมาก ผมจึงอยากจะแสดงเคล็ดลับเจ๋ง ๆ นี้ด้วย แม้ว่าจะไม่ค่อยมีประโยชน์เท่าคำตอบหลักของผม แต่จะขอแนะนำวิธี repeat() ของ String ที่ยังไม่ค่อยมีใครรู้จัก แต่มีประโยชน์มาก นี่คือเคล็ดลับ:

> "?".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]

คำตอบ #5

วิธี fill ของ ES 6 ที่ได้กล่าวถึงแล้วจัดการเรื่องนี้ได้ดีมาก เบราว์เซอร์สำหรับเดสก์ท็อปสมัยใหม่ส่วนใหญ่รองรับเมธอดของ Array prototype ที่จำเป็นในปัจจุบันแล้ว (Chromium, FF, Edge และ Safari) [1] คุณสามารถดูรายละเอียดเพิ่มเติมได้ที่ MDN ตัวอย่างการใช้งานง่าย ๆ คือ

a = new Array(10).fill(0);

ด้วยการสนับสนุนเบราว์เซอร์ในปัจจุบัน คุณควรระมัดระวังในการใช้สิ่งนี้ เว้นแต่ว่าคุณแน่ใจว่าผู้ชมของคุณใช้เบราว์เซอร์เดสก์ท็อปสมัยใหม่

คำตอบ #6

หมายเหตุเพิ่มเติม สิงหาคม 2013 อัปเดต กุมภาพันธ์ 2015: คำตอบด้านล่างจากปี 2009 เกี่ยวข้องกับประเภท Array ทั่วไปของ JavaScript ซึ่งไม่ได้เกี่ยวข้องกับอาเรย์ typed ใหม่ที่กำหนดใน ES2015 [และสามารถใช้ได้ในหลายเบราว์เซอร์ตอนนี้] เช่น Int32Array และอื่นๆ นอกจากนี้ โปรดทราบว่า ES2015 เพิ่มเมธอด fill ทั้งใน Arrays และ typed arrays ซึ่งน่าจะเป็นวิธีที่มีประสิทธิภาพที่สุดในการเติมข้อมูลให้กับพวกมัน...


กับภาษาส่วนใหญ่ จะเป็นการจัดสรรล่วงหน้า แล้วเติมศูนย์ เช่นนี้:

function newFilledArray(len, val) {
    var rv = new Array(len);
    while (--len >= 0) {
        rv[len] = val;
    }
    return rv;
}

แต่ อาร์เรย์ใน JavaScript จริง ๆ แล้วไม่ใช่อาร์เรย์ พวกมันเป็นแผนที่คีย์/ค่า เช่นเดียวกับอ็อบเจ็กต์ JavaScript อื่น ๆ ดังนั้นจึงไม่มีการ "จัดสรรล่วงหน้า" ที่ต้องทำ (การตั้งความยาวไม่ได้จัดสรรช่องสำหรับเติมให้ครบจำนวน) และก็ไม่มีเหตุผลที่จะเชื่อว่าประโยชน์ของการนับลงจนถึงศูนย์ (ซึ่งเป็นเพียงเพื่อทำให้การเปรียบเทียบในลูปเร็วขึ้น) จะไม่ถูกลบล้างด้วยการเพิ่มคีย์ในลำดับย้อนกลับเมื่อการใช้งานอาจได้เพิ่มประสิทธิภาพการจัดการคีย์ที่เกี่ยวข้องกับอาร์เรย์โดยสมมติว่าปกติคุณจะทำพวกมันตามลำดับ

ในความเป็นจริง Matthew Crumley ชี้ให้เห็นว่าการนับถอยหลังก็ชัดเจนว่าสูงกว่าในการใช้ Firefox เมื่อเทียบกับการนับขึ้น ซึ่งเป็นผลลัพธ์ที่ผมสามารถยืนยันได้ — มันเป็นเพราะส่วนของอาร์เรย์ (การวนลูปลงถึงศูนย์นั้นยังเร็วกว่าการวนลูปขึ้นไปจนถึงขีดจำกัดในตัวแปร) เห็นได้ชัดว่าการเพิ่มองค์ประกอบลงในอาร์เรย์ในลำดับย้อนกลับเป็นการทำงานที่ช้าบน Firefox ในความเป็นจริงผลลัพธ์จะแตกต่างกันอย่างมากตามการใช้งาน JavaScript (ซึ่งก็ไม่ใช่เรื่องน่าประหลาดใจมากนัก) นี่คือหน้าทดสอบอย่างรวดเร็วและหยาบ (ด้านล่าง) สำหรับการใช้งานเบราว์เซอร์ (หยาบมาก ไม่ยอมให้พักระหว่างการทดสอบ ดังนั้นให้ข้อมูลตอบกลับน้อย และจะเจอข้อจำกัดเวลาในการรันสคริปต์) ผมแนะนำให้รีเฟรชหน้าระหว่างการทดสอบ; อย่างน้อยใน Firefox จะช้าลงหากทดสอบซ้ำโดยไม่รีเฟรช

เวอร์ชันที่ซับซ้อนพอสมควรซึ่งใช้ Array#concat นั้นเร็วกว่าการเริ่มต้นตรง ๆ บน FF เมื่อจำนวนอาเรย์อยู่ระหว่าง 1,000 ถึง 2,000 องค์ประกอบ แต่บนเอนจิน V8 ของ Chrome การเริ่มต้นตรง ๆ จะชนะทุกครั้ง...

นี่คือตัวทดสอบ:

const tests = [
    {
        name:   "downpre",
        total:  0,
        desc:   "Count down, pre-decrement",
        func:   makeWithCountDownPre
    },
    {
        name:   "downpost",
        total:  0,
        desc:   "Count down, post-decrement",
        func:   makeWithCountDownPost
    },
    {
        name:   "up",
        total:  0,
        desc:   "Count up (normal)",
        func:   makeWithCountUp
    },
    {
        name:   "downandup",
        total:  0,
        desc:   "Count down (for loop) and up (for filling)",
        func:   makeWithCountDownArrayUp
    },
    {
        name:   "concat",
        total:  0,
        desc:   "Concat",
        func:   makeWithConcat
    }
];

const q = sel => document.querySelector(sel);

let markup = "";
for (const {name, desc} of tests) {
    markup += `
        <div><input type="checkbox" id="chk_${name}" checked>
        <label for="chk_${name}">${desc}</label></div>`;
}
q("#checkboxes").innerHTML = markup;
q("#btnTest").addEventListener("click", btnTestClick);

function btnTestClick() {
    // Clear log
    q("#log").innerHTML = "Testing...";

    // Show running
    q("#btnTest").disabled = true;

    // Run after a pause while the browser updates display
    setTimeout(btnTestClickPart2, 0);
}

function btnTestClickPart2() {
    try {
        runTests();
    } catch (e) {
        log(`Exception: ${e.message}`);
    }

    // Re-enable the button
    q("#btnTest").disabled = false;
}

function getNumField(name) {
    const val = q("#" + name).value.trim();
    const num = /^\d+$/.test(val) ? parseInt(val) : NaN;
    if (isNaN(num) || num <= 0) {
        throw new Error(`Invalid ${name} value ${JSON.stringify(val)}`);
    }
    return num;
}

function runTests() {
    try {
        // Clear log
        q("#log").innerHTML = "";

        const runCount = getNumField("loops");
        const length = getNumField("length");

        // Do it (we run runCount + 1 times, first time is a warm up)
        for (let counter = 0; counter <= runCount; ++counter) {
            for (const test of tests) {
                if (q("#chk_" + test.name).checked) {
                    const start = Date.now();
                    const a = test.func(length);
                    const time = Date.now() - start;
                    if (counter == 0) {
                        // Don't count (warm up), but do check the algorithm works
                        const invalid = validateResult(a, length);
                        if (invalid) {
                            log(`<span class=error>FAILURE</span> with test ${test.name}: ${invalid}`);
                            return;
                        }
                    } else {
                        // Count this one
                        log(`#${counter}: ${test.desc}: ${time}ms`);
                        test.total += time;
                    }
                }
            }
        }

        for (const test of tests) {
            if (q("#chk_" + test.name).checked) {
                test.avg = test.total / runCount;
                if (typeof lowest != "number" || lowest > test.avg) {
                    lowest = test.avg;
                }
            }
        }

        let results =
            "<p>Results:" +
            "<br>Length: " + length +
            "<br>Loops: " + runCount +
            "</p>";
        for (const test of tests) {
            if (q("#chk_" + test.name).checked) {
                results +=
                    `<p ${lowest == test.avg ? " class=winner" : ""}>${test.desc}, average time: ${test.avg}ms</p>`;
            }
        }
        results += "<hr>";
        q("#log").insertAdjacentHTML("afterbegin", results);
    } catch (e) {
        log(e.message);
        return;
    }
}

function validateResult(a, length) {
    if (a.length != length) {
        return "Length is wrong";
    }
    for (let n = length - 1; n >= 0; --n) {
        if (a[n] != 0) {
            return "Index " + n + " is not zero";
        }
    }
    return undefined;
}

function makeWithCountDownPre(len) {
    const a = new Array(len);
    while (--len >= 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountDownPost(len) {
    const a = new Array(len);
    while (len-- > 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountUp(len) {
    const a = new Array(len);
    for (let i = 0; i < len; ++i) {
        a[i] = 0;
    }
    return a;
}

function makeWithCountDownArrayUp(len) {
    const a = new Array(len);
    let i = 0;
    while (--len >= 0) {
        a[i++] = 0;
    }
    return a;
}

function makeWithConcat(len) {
    if (len == 0) {
        return [];
    }
    let a = [0];
    let currlen = 1;
    while (currlen < len) {
        const 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) {
    const p = document.createElement("p");
    p.textContent = msg;
    q("#log").appendChild(p);
}
body {
    font-family: sans-serif;
}
#log p {
    margin: 0;
    padding: 0;
}
.error {
    color: red;
}
.winner {
    color: green;
}
<div>
<label for='txtLength'>Length:</label><input type='text' id='length' value='1000'>
<br><label for='txtLoops'>Loops:</label><input type='text' id='loops' value='100000'>
<div id='checkboxes'></div>
<br><input type='button' id='btnTest' value='Test'>
<hr>
<div id='log'></div>
</div>

คำตอบ #7

ถ้าคุณใช้ 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]

คำตอบ #8

โดยค่าเริ่มต้น คลาส Uint8Array, Uint16Array และ Uint32Array จะเก็บค่าเป็นศูนย์ ดังนั้นคุณไม่จำเป็นต้องใช้เทคนิคการเติมที่ซับซ้อน แค่ทำดังนี้:

var ary = new Uint8Array(10);

ทุกองค์ประกอบของอาร์เรย์ ary จะเป็นศูนย์โดยค่าเริ่มต้น

คำตอบ #9

การใช้สัญลักษณ์วัตถุ

var x = [];

เติมศูนย์ไหม? แบบว่า...

var x = [0,0,0,0,0,0];

เต็มไปด้วย 'undefined'...

var x = new Array(7);

การเขียนสัญลักษณ์ obj พร้อมศูนย์

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

เป็นข้อสังเกตเพิ่มเติม หากคุณแก้ไขโปรโตไทป์ของ Array ทั้งคู่

var x = new Array();

และ

var y = [];

จะมีการปรับเปลี่ยนต้นแบบเหล่านั้น

อย่างไรก็ตาม ผมคงไม่ต้องกังวลมากเกินไปเกี่ยวกับประสิทธิภาพหรือความเร็วของกระบวนการนี้ เพราะยังมีสิ่งอื่น ๆ อีกมากมายที่คุณน่าจะทำซึ่งสิ้นเปลืองและมีค่าใช้จ่ายมากกว่าการสร้างอาเรย์ความยาวใดก็ได้ที่มีค่าเป็นศูนย์

คำตอบ #10

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 เป็นต้น

คำตอบ #11

ฉันได้ทดสอบทุกการผสมของการจองล่วงหน้า/ไม่จองล่วงหน้า การนับขึ้น/นับลง และลูป for/while ใน IE 6/7/8, Firefox 3.5, Chrome และ Opera แล้ว

ฟังก์ชันด้านล่างนี้มีความเร็วสม่ำเสมอที่สุดหรือใกล้เคียงที่สุดใน Firefox, Chrome และ IE8 และไม่ได้ช้ากว่าฟังก์ชันที่เร็วที่สุดใน Opera และ IE6 มากนัก นอกจากนี้ยังเป็นฟังก์ชันที่ง่ายที่สุดและชัดเจนที่สุดตามความเห็นของฉัน ฉันพบว่ามีบางเบราว์เซอร์ที่เวอร์ชันลูป while ทำงานเร็วกว่าเล็กน้อย ดังนั้นฉันจึงรวมมันไว้ด้วยเพื่อเป็นข้อมูลอ้างอิง

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;
}

คำตอบ #12

const arr = Array.from({ length: 10 }).fill(0);
console.log(arr)

คำตอบ #13

วิธีแก้ปัญหา ES6:

[...new Array(5)].map(x => 0); // [0, 0, 0, 0, 0]

คำตอบ #14

หากคุณจำเป็นต้องสร้างอาเรย์ที่เต็มด้วยศูนย์หลายอาเรย์ที่มีความยาวต่างกันในระหว่างการทำงานของโค้ด วิธีที่เร็วที่สุดที่ฉันพบในการทำเช่นนี้คือการสร้างอาเรย์ที่เต็มด้วยศูนย์ ครั้งเดียว โดยใช้หนึ่งในวิธีที่กล่าวถึงในหัวข้อนี้ ของความยาวที่คุณรู้ว่าจะไม่มีการเกิน และจากนั้นจึงตัดอาเรย์นั้นตามความจำเป็น

ตัวอย่างเช่น (ใช้ฟังก์ชันจากคำตอบที่เลือกด้านบนเพื่อเริ่มต้นอาร์เรย์) สร้างอาร์เรย์ที่เติมด้วยศูนย์มีความยาว maxLength เป็นตัวแปรที่มองเห็นได้สำหรับโค้ดที่ต้องการอาร์เรย์ที่เต็มด้วยศูนย์:

var zero = newFilledArray(maxLength, 0);

ตอนนี้ตัดอาร์เรย์นี้ทุกครั้งที่คุณต้องการอาร์เรย์ที่เติมด้วยศูนย์ความยาว requiredLength < maxLength:

zero.slice(0, requiredLength);

ฉันเคยสร้างอาเรย์ที่เติมด้วยศูนย์เป็นพัน ๆ ครั้งระหว่างการรันโค้ดของฉัน ซึ่งเร่งกระบวนการได้อย่างมาก

คำตอบ #15

function zeroFilledArray(size) {
    return new Array(size + 1).join('0').split('');
}

คำตอบ #16

การใช้ lodash หรือ underscore

_.range(0, length - 1, 0);

หรือหากคุณมีอาเรย์อยู่แล้วและคุณต้องการอาเรย์ที่มีความยาวเท่ากัน

array.map(_.constant(0));

คำตอบ #17

ฉันไม่มีอะไรต่อต้าน:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);

แนะนำโดย Zertosh แต่ในส่วนขยายอาร์เรย์ ES6 ใหม่ คุณสามารถทำสิ่งนี้ได้โดยตรงด้วยเมธอด fill ตอนนี้ IE Edge, Chrome และ FF รองรับแล้ว แต่ตรวจสอบตารางความเข้ากันได้

`new Array(3).fill(0)` จะให้คุณ `[0, 0, 0]` คุณสามารถเติมค่าลงในอาเรย์ด้วยค่าต่าง ๆ ได้เช่น `new Array(5).fill('abc')` (สามารถใช้วัตถุและอาเรย์อื่น ๆ ได้ด้วย)

นอกจากนี้คุณยังสามารถแก้อาร์เรย์ก่อนหน้าด้วย fill:

arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5)  # what to fill, start, end

ซึ่งจะให้คุณได้: [1, 2, 3, 9, 9, 6]

คำตอบ #18

เพื่อสร้างอาร์เรย์ใหม่ทั้งหมด

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

คำตอบ #19

วิธีที่ฉันมักทำ (และเร็วมาก) คือการใช้ Uint8Array ตัวอย่างเช่น การสร้างเวกเตอร์ที่เติมด้วยศูนย์จำนวน 1 ล้านองค์ประกอบ:

  var zeroFilled = [].slice.apply(new Uint8Array(1000000))

ฉันเป็นผู้ใช้ Linux และมันก็ใช้ได้เสมอสำหรับฉัน แต่ครั้งหนึ่งเพื่อนที่ใช้ Mac มีบางองค์ประกอบที่ไม่เป็นศูนย์ ฉันคิดว่าเครื่องของเขามีปัญหา แต่ถึงอย่างนั้น นี่คือวิธีที่ปลอดภัยที่สุดที่เราพบเพื่อแก้ไข:

  var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000)) 

แก้ไขแล้ว

โครม 25.0.1364.160

  1. เฟรเดอริก กอตลีบ - 6.43
  2. แซม บาร์นัม - 4.83
  3. อีไล - 3.68
  4. โยชูวา 2.91
  5. แมทธิว ครัมลีย์ - 2.67
  6. bduran - 2.55
  7. อัลเลน ไรซ์ - 2.11
  8. kangax - 0.68
  9. ทีเจ คราวเดอร์ - 0.67
  10. zertosh - ข้อผิดพลาด

ไฟร์ฟอกซ์ 20.0

  1. อัลเลน ไรซ์ - 1.85
  2. ยอชูวา - 1.82
  3. แมทธิว ครัมลีย์ - 1.79
  4. bduran - 1.37
  5. เฟรเดอริก กอตลีบ - 0.67
  6. แซม บาร์นัม - 0.63
  7. อีไล - 0.59
  8. kagax - 0.13
  9. ทีเจ คราวเดอร์ - 0.13
  10. zertosh - ข้อผิดพลาด

พลาดการทดสอบที่สำคัญที่สุด (อย่างน้อยก็สำหรับฉัน): การทดสอบ Node.js ฉันสงสัยว่ามันใกล้กับมาตรฐานของ Chrome

บทความที่เกี่ยวข้อง