Наиболее эффективный способ добавления значения к массиву
Предполагая, что у меня есть массив размером N
(где N > 0
), существует ли более эффективный способ добавления массива, который не требует шагов O (N + 1)?
В коде, по существу, то, что я делаю сейчас,
function prependArray(value, oldArray) {
var newArray = new Array(value);
for(var i = 0; i < oldArray.length; ++i) {
newArray.push(oldArray[i]);
}
return newArray;
}
Ответы
Ответ 1
Я не уверен насчет более эффективного с точки зрения big-O, но, конечно, использование метода unshift
более лаконично:
var a = [1, 2, 3, 4];
a.unshift(0);
a; // => [0, 1, 2, 3, 4]
[Редактировать]
Этот тест jsPerf показывает, что unshift
работает прилично быстрее, по крайней мере, в нескольких браузерах, независимо от возможной разной производительности big-O, если вы согласны с изменением массива на месте. Если вы действительно не можете изменить исходный массив, сделайте что-то вроде приведенного ниже фрагмента, который, похоже, не будет значительно быстрее, чем ваше решение:
a.slice().unshift(0); // Use "slice" to avoid mutating "a".
[Редактировать 2]
Для полноты можно использовать следующую функцию вместо примера OP prependArray(...)
чтобы воспользоваться преимуществом метода Array unshift(...)
:
function prepend(value, array) {
var newArray = array.slice();
newArray.unshift(value);
return newArray;
}
var x = [1, 2, 3];
var y = prepend(0, x);
y; // => [0, 1, 2, 3];
x; // => [1, 2, 3];
Ответ 2
Если вы добавляете массив к фронту другого массива, более эффективно использовать concat
. Итак:
var newArray = values.concat(oldArray);
Но это все равно будет O (N) в размере oldArray. Тем не менее, он более эффективен, чем ручное повторение по сравнению с oldArray. Кроме того, в зависимости от деталей, это может вам помочь, потому что, если вы собираетесь добавить много значений, лучше сначала поместить их в массив, а затем конкатенерировать oldArray на конце, а не добавлять каждый отдельно.
Нет никакого способа сделать лучше, чем O (N) в размере oldArray, потому что массивы хранятся в непрерывной памяти с первым элементом в фиксированной позиции. Если вы хотите вставить перед первым элементом, вам нужно переместить все остальные элементы. Если вам нужно обойти это, сделайте то, что сказал @GWW, и используйте связанный список или другую структуру данных.
Ответ 3
С ES6 вы можете теперь использовать оператор распространения, чтобы создать новый массив с вашими новыми элементами, вставленными перед исходными элементами.
// Prepend a single item.
const a = [1, 2, 3];
console.log([0, ...a]);
Ответ 4
Если вы хотите добавить массив (a1 с массивом a2), вы можете использовать следующее:
var a1 = [1, 2];
var a2 = [3, 4];
Array.prototype.unshift.apply(a1, a2);
console.log(a1);
// => [3, 4, 1, 2]
Ответ 5
f вам нужно сохранить старый массив,
отрежьте старый и не сдвиньте новое значение (ы)
к началу среза.
var oldA=[4,5,6];
newA=oldA.slice(0);
newA.unshift(1,2,3)
oldA+'\n'+newA
/* returned value:
4,5,6
1,2,3,4,5,6
*/
Ответ 6
Существует специальный метод:
a.unshift(value);
Но если вы хотите добавить несколько элементов в массив, было бы быстрее использовать такой метод:
var a = [1, 2, 3],
b = [4, 5];
function prependArray(a, b) {
var args = b;
args.unshift(0);
args.unshift(0);
Array.prototype.splice.apply(a, args);
}
prependArray(a, b);
console.log(a); // -> [4, 5, 1, 2, 3]
Ответ 7
У меня есть несколько свежих тестов различных методов приготовления. Для небольших массивов (<1000 элементов) лидером является цикл, связанный с методом push. Для огромных массивов метод Unshift становится лидером.
Но эта ситуация актуальна только для браузера Chrome. В Firefox unshift имеет потрясающую оптимизацию и работает быстрее во всех случаях.
ES6 распространяется в 100+ раз медленнее во всех браузерах.
https://jsbench.me/cgjfc79bgx/1
Ответ 8
Пример добавления на месте:
var A = [7,8,9]
var B = [1,2,3]
A.unshift(...B)
console.log(A) // [1,2,3,7,8,9]
Ответ 9
Вызов unshift
возвращает только длину нового массива. Итак, чтобы добавить элемент в начале и вернуть новый массив, я сделал это:
let newVal = 'someValue';
let array = ['hello', 'world'];
[ newVal ].concat(array);
или просто с оператором распространения:
[ newVal, ...array ]
Таким образом, исходный массив остается нетронутым.