Ініціалізація масиву з одним значенням


Відповіді:


44
while(arraySize--) array.push(value);

відсутність ініціалізації (про яку я знаю)


Оновлення

З тих пір, як колись публікували цю відповідь 4 роки тому, люди, здається, постійно повертаються сюди за цією відповіддю. Для порівняльних цілей я створив JSPerf з різними рішеннями.

Рішення вище не найшвидше, хоча воно і коротке. Щоб дотримуватися того самого короткого стилю, але з кращими показниками:

while(size--) array[size] = value;

Оновлення лютого 2016 р. Оновлено JSPerf новою версією з більшою кількістю тестових випадків.

Якщо продуктивність не має значення, і ви хочете однокласний:

var value = 1234, // can be replaced by a fixed value
    size  = 1000, // can be replaced by a fixed value
    array = Array.apply(null,{length: size}).map(function() { return value; });

Більш ефективне рішення (в одному, брудному, рядку): Майте на увазі: це замінює існуючі значення, розмір та i змінні в області

for(var i = 0, value = 1234, size = 1000, array = new Array(1000); i < size; i++) array[i] = value;

У багатьох випадках “arraySize” не можна змінювати (це може бути константа або літерал або - я знаю, погана практика - “array.length”). Представляючи розмір як змінну, я зробив це трохи незрозумілим.
найстарішийживий хлопець

1
true: "for (var i = arraySize; i--;) array.push (value);" тоді :-) але я думаю ви це вже
зрозуміли

1
Ви маєте рацію - цей синтаксис справді збриває п’ять символів. ;-)
старшийживий хлопець

3
whileв 2 рази повільніше, ніж forу JavaScript, а прості перевірки на кшталт if (number)також повільніші, ніж if (number === 0)через перетворення типу (це також стосується булевих значень, рядків та нулів). Цьому мене навчили мої тести jsPerf.
Triang3l

2
новий масив (len) .fill (0);
Мухаммед Умер

136

Короткий спосіб зробити це:

var arr = Array(arraySize).fill(value);

Зробив би arr = Array [ 0, 0, 0, 0, 0 ]якщо arraySize == 5і value == 0, наприклад.



23
@Perry. Ви знаєте, коли браузер з 6% ринку не підтримує стандарт, це проблема цього браузера
Слава

12
Будьте обережні з функцією заливки, якщо значенням є об’єкт, оскільки у вас може бути один і той же об’єкт у всьому масиві, що може спричинити небажані результати.
Gregzenegair

9

Здається, ОП вимагає компактності в сценарії одноразового використання щодо ефективності та повторного використання. Для інших, хто шукає ефективності, ось оптимізація, про яку ще не згадувалося. Оскільки ви заздалегідь знаєте довжину масиву, продовжуйте і встановлюйте його перед присвоєнням значень. В іншому випадку масив буде неодноразово змінюватись на льоту - не ідеально!

function initArray(length, value) {
    var arr = [], i = 0;
    arr.length = length;
    while (i < length) { arr[i++] = value; }
    return arr;
}

var data = initArray(1000000, false);

1
У JavaScript forце в 2 рази швидше, ніж while.
Triang3l

2
Я б не сказав, що це настільки точно: stoimen.com/blog/2012/01/24/javascript-performance-for-vs-, звичайно, ви не хотіли б завжди використовувати будь-яке виключно - це перешкоджає їх цілі. Робота перекладача / компілятора повинна бути пришвидшити його там, де це можливо, а не вам. Але навіть це не завжди правда.
Арам Кочарян

9

Це не настільки компактно, але, можливо, є більш прямим.

array = Array.apply(null, new Array(arraySize)).map(function () {return value;});

5

Це, швидше за все, не буде кращим за будь-який із наведених вище методів, але це цікаво ...

var a = new Array(10).join('0').split('').map(function(e) {return parseInt(e, 10);})

Ви можете пояснити, чому var arr = (new Array(5)).map(() => 1);не працює?
Бхарат Гупта,

1
Метод map () працює лише зі значеннями в масиві. Він пропускає невизначені елементи.
Крістофер Вайс

Отже, після того, new Array(5)як ми робимо карту, чи не оперуємо ми масивом? Крім того, це [1,undefined,3].map(() => 5)працює, як очікувалося. Це не пропускаєundefined
Бхарат Гупта,

2
З документації mozilla за адресою developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… : map викликає надану функцію зворотного виклику один раз для кожного елемента в масиві, і створює новий масив з результатів . callback викликається лише для індексів масиву, яким присвоєні значення, включаючи undefined. Він не викликається для відсутніх елементів масиву (тобто індексів, які ніколи не встановлювались, які були видалені або яким ніколи не було присвоєно значення).
Крістофер Вайс

Приголомшливо Дякую @Christopher!
Бхарат Гупта,

4

Це старе питання, але я використовую це в сучасній JS:

[...new Array(1000000)].map(()=>42);

2

Для ефективності я б уникав push. Так просто

for (var i = 0; i < arraySize; i++) array[i] = value; 

Для IE10:

array = new Array(arraySize); 
for (var i = 0; i < arraySize; i++) array[i] = value; 

Редагувати: змінено, як обговорювалось у коментарях.


for (var i = 0; i < arraySize; ++i)має майже таку ж продуктивність, як і ваш код, але виглядає чистішим. Але while (arraySize--)це в 2 рази повільніше.
Triang3l

Так, але розподіл пам’яті для arrayбільш ефективний, ніж запуск array[0].
Kyaw Tun

2
Ні. Якщо ви починаєте ініціалізувати масив з кінця, хеш-таблиці будуть використовуватися всередині, але якщо ви починаєте ініціалізувати масив з 0, і у вас є лише послідовні індекси, буде використовуватися справжній масив (принаймні у V8). JavaScript не виділяє (найвищий_індекс + 1) елементи, він виділяє лише ініціалізовані елементи.
Triang3l

З обговорення [Build / 12] ( channel9.msdn.com/Events/Build/2012/4-000 ) IE10 потребує попереднього розподілу, щоб бути ефективним. Посилання [на слайді 54] ( channel9.msdn.com/Events/Build/2012/4-000 )
Tun

1

Якщо вам потрібно це зробити багато разів, ви завжди можете написати функцію:

function makeArray(howMany, value){
    var output = [];
    while(howMany--){
        output.push(value);
    }
    return output;
}

var data = makeArray(40, "Foo");

І лише для повноти (возитися з прототипом вбудованих об’єктів часто не є гарною ідеєю):

Array.prototype.fill = function(howMany, value){
    while(howMany--){
        this.push(value);
    }
}

Тож тепер ви можете:

var data = [];
data.fill(40, "Foo");

Оновлення: Я щойно бачив вашу нотатку про arraySizeте, що це константа або буквал. Якщо так, просто замініть усіх while(howMany--)на старі добрі for(var i=0; i<howMany; i++).


1

Натрапивши на це, досліджуючи масивні методи на літаку .. ооо, місця, куди ми їдемо, коли нам нудно. :)

var initializedArray = new Array(30).join(null).split(null).map(function(item, index){
  return index;
});

.map()і nullдля перемоги! Мені подобається null, тому що передача в рядок, як вгорі, з "0" або будь-яким іншим значенням заплутує. Я думаю, це більш чітко, що ми робимо щось інше.

Зверніть увагу, що .map()пропускає неініціалізовані значення. Ось чому new Array(30).map(function(item, index){return index});не працює. Новий .fill()метод є кращим, якщо він доступний, однак підтримка браузера повинна бути зазначена станом на 23.08.2015 .

Робочий стіл (базова підтримка)

  • Chrome 45 (36 1 )
  • Firefox (Gecko) 31 (31)
  • Internet Explorer Не підтримується
  • Opera Не підтримується
  • Safari 7.1

З MDN :

[1, 2, 3].fill(4);               // [4, 4, 4]
[1, 2, 3].fill(4, 1);            // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2);         // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1);         // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2);       // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN);     // [1, 2, 3]
Array(3).fill(4);                // [4, 4, 4]
[].fill.call({ length: 3 }, 4);  // {0: 4, 1: 4, 2: 4, length: 3}

Сьогодні це (червень 2019 р.) Легко записати так: [...Array(30)].map((_, i) => i);
magikMaker
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.