Самый эффективный способ создать массив JavaScript с нулевым заполнением?

PL / SQL включает базовый для списков, разделенных запятыми (DBMS_UTILITY.COMMA_TO_TABLE).

Пример:

DECLARE
   lv_tab_length   BINARY_INTEGER;
   lt_array   DBMS_UTILITY.lname_array;
BEGIN
   DBMS_UTILITY.COMMA_TO_TABLE( list => 'one,two,three,four'
                              , tablen => lv_tab_length
                              , tab => lt_array
                              );

   DBMS_OUTPUT.PUT_LINE( 'lv_tab_length = ['||lv_tab_length||']' );

   FOR i IN 1..lv_tab_length
   LOOP
      DBMS_OUTPUT.PUT_LINE( '['||lt_array( i )||']' );
   END LOOP;

END;
/

Или см. ссылку Ask Tom для других идей. ..

Ak Tom - «различные элементы в списке IN»

512
задан dil 18 August 2009 в 18:11
поделиться

9 ответов

let filled = [];
filled.length = 10;
filled.fill(0);

console.log(filled);
3
ответ дан 22 November 2019 в 22:20
поделиться

Я знал, что где-то у меня был этот прототип :)

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

Edit: tests

В ответ на методы Джошуа и других я провел свой собственный тест, и я увидел совершенно другое

Вот то, что я тестировал:

//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

Итак, по моим подсчетам, push действительно медленнее в целом, но работает лучше с более длинными массивами в FF, но хуже в IE, что в целом отстой (quel сюрприз ).

3
ответ дан 22 November 2019 в 22:20
поделиться
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']

Обратите внимание, что , а обычно более эффективен, чем for-in , forEach и т. Д.

23
ответ дан 22 November 2019 в 22:20
поделиться

Я протестировал все комбинации предварительного выделения / отсутствия предварительного выделения, подсчета вверх / вниз и циклов for / while в IE 6/7/8, Firefox 3.5, Chrome и Opera.

Приведенные ниже функции всегда были самыми быстрыми или очень близкими в Firefox, Chrome и IE8, и ненамного медленнее, чем самые быстрые в Opera и IE 6. На мой взгляд, они также самые простые и понятные. Я нашел несколько браузеров, в которых версия цикла 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;
}
20
ответ дан 22 November 2019 в 22:20
поделиться

Примечание добавлено в августе 2013 г., обновлено в феврале 2015 г .: Приведенный ниже ответ от 2009 г. относится к общему типу JavaScript Array . Это не относится к более новым типизированным массивам, определенным в ES2015 [и теперь доступным во многих браузерах], таким как Int32Array и т.п. Также обратите внимание, что ES2015 добавляет метод fill к типизированным массивам Arrays и , что, вероятно, будет наиболее эффективным способом их заполнения ...

Кроме того, это может иметь большое значение для некоторых реализаций того, как вы создаете массив. Механизм Chrome V8, в частности, пытается использовать высокоэффективный массив непрерывной памяти, если считает, что это возможно, переходя к объектно-ориентированному массиву только при необходимости.


В большинстве языков это будет предварительно выделено, затем заполнение нулями, вот так: По-видимому, добавление элементов в массив в обратном порядке - медленная операция в Firefox. Фактически, результаты довольно сильно различаются в зависимости от реализации JavaScript (что не так уж удивительно). Вот быстрая и грязная тестовая страница (ниже) для реализаций браузера (очень грязная, не срабатывает во время тестов, поэтому обеспечивает минимальную обратную связь и будет нарушать ограничения по времени скрипта). Я рекомендую обновляться между тестами; FF (по крайней мере) замедляется при повторных тестах, если вы этого не сделаете.

Достаточно сложная версия, использующая Array # concat, быстрее, чем прямая инициализация на FF, где-то между 1000 и 2000 массивами элементов. Однако на движке Chrome V8 прямой init побеждает каждый раз ...

Вот тестовая страница ( живая копия ):

<!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>
50
ответ дан 22 November 2019 в 22:20
поделиться

с использованием объектной нотации

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 = [];

будут иметь эти модификации прототипа

Во всяком случае, меня бы не слишком беспокоила эффективность или скорость этой операции, вы, вероятно, будете делать множество других вещей, которые намного расточительнее и дороже, чем создание экземпляра массива произвольной длины, содержащего нули. .

18
ответ дан 22 November 2019 в 22:20
поделиться

Моя самая быстрая функция:

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

Использование собственных push и shift для добавления элементов в массив намного быстрее (примерно в 10 раз), чем объявление области массива и ссылка на каждый элемент для установки это значение.

к сведению: я постоянно получаю более быстрое время с первым циклом, который идет обратным отсчетом, при запуске этого в firebug (расширение firefox).

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

Мне интересно знать, что TJ Crowder делает из этого? : -)

4
ответ дан 22 November 2019 в 22:20
поделиться

const arr = Array.from({ length: 10 })
0
ответ дан 22 November 2019 в 22:20
поделиться
var str = "0000000...0000";
var arr = str.split("");

использование в выражениях: arr [i] * 1;

РЕДАКТИРОВАТЬ: если arr предполагается использовать в целочисленных выражениях, пожалуйста, не Обратите внимание на значение символа "0". Вы просто используете его следующим образом: a = a * arr [i] (при условии, что a имеет целочисленное значение).

1
ответ дан 22 November 2019 в 22:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: