Как я могу добавить новые элементы массива в начале массива в Javascript?


1590

У меня есть необходимость добавлять или добавлять элементы в начале массива.

Например, если мой массив выглядит следующим образом:

[23, 45, 12, 67]

И ответ на мой вызов AJAX: 34я хочу, чтобы обновленный массив был таким:

[34, 23, 45, 12, 67]

В настоящее время я планирую сделать это так:

var newArray = [];
newArray.push(response);

for (var i = 0; i < theArray.length; i++) {
    newArray.push(theArray[i]);
}

theArray = newArray;
delete newArray;

Есть ли лучший способ сделать это? Есть ли в Javascript какие-либо встроенные функции, которые это делают?

Сложность моего метода в том, O(n)и было бы очень интересно увидеть лучшие реализации.


9
К сведению: если вам нужно постоянно вставлять элемент в начале массива, быстрее использовать pushоператоры, сопровождаемые вызовом reverse, вместо того, чтобы вызывать unshiftвсе время.
— Дженни О'Рейли

2
@ JennyO'Reilly, ты должен опубликовать это как ответ. Идеально подходит для моего варианта использования. спасибо
— грабить

2
Тесты производительности: jsperf.com/adding-element-to-the-array-start Но результаты отличаются для каждого браузера.
— Avernikoz

Ответы:


2818

Использование unshift. Это как push, за исключением того, что он добавляет элементы в начало массива вместо конца.

  • unshift/ push- добавить элемент в начало / конец массива
  • shift/ pop - удалить и вернуть первый / последний элемент массива

Простая схема ...

   unshift -> array <- push
   shift   <- array -> pop

и диаграмма:

          add  remove  start  end
   push    X                   X
    pop           X            X
unshift    X             X
  shift           X      X

Ознакомьтесь с документацией по массиву MDN . Практически каждый язык, который имеет возможность вставлять / извлекать элементы из массива, также будет иметь возможность отменять / сдвигать (иногда называемые push_front/ pop_front) элементы, вам никогда не придется реализовывать их самостоятельно.


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

const array = [ 3, 2, 1 ]

const newFirstElement = 4

const newArray = [newFirstElement].concat(array) // [ 4, 3, 2, 1 ]

concatМожно также добавлять элементы. Аргументы concatмогут быть любого типа; они неявно заключены в одноэлементный массив, если они еще не являются массивом:

const array = [ 3, 2, 1 ]

const newLastElement  = 0

// Both of these lines are equivalent:
const newArray1 = array.concat(newLastElement)   // [ 3, 2, 1, 0 ]
const newArray2 = array.concat([newLastElement]) // [ 3, 2, 1, 0 ]

52
Использование concatможет быть предпочтительнее, поскольку оно возвращает новый массив. Очень полезно для цепочки. [thingToInsertToFront].concat(originalArray).reduce(fn).reverse().map(fn)и т.д ... Если вы используете unshift, вы не можете сделать эту цепочку, потому что все, что вы получите, это длина.
— StJohn3D

4
Shift / Unshift, Push / Pop, соединение. Очень логичные названия для таких методов.
— linuxunil

1400

изображение операций с массивами

var a = [23, 45, 12, 67];
a.unshift(34);
console.log(a); // [34, 23, 45, 12, 67]


117
Причина, по которой людям нужны визуальные ориентиры для 4-х используемых ежедневно функций, заключается в зашифрованных именах функций ... Почему unshift не называется Insert? Сдвиг должен быть Удалить. и т.д ...
— Паскаль

76
// Почему unshift не называется Insert? // Это происходит из соглашений языка программирования C, где элементы массива обрабатываются как стек. ( полное объяснение см. в perlmonks.org/?node_id=613129 )
— dreftymac

25
@Pascal Нет, вставка и удаление будут особенно плохими именами для этого; они подразумевают произвольный доступ, вместо добавления / удаления из передней части массива
— meagar

25
Я бы подумал, что unshift должен удалить первый ключ, а shift вставил бы первый ключ, но это всего лишь моя общая мысль
— Шеннон Хохкинс

27
Мне нравится ссылка на ДНК
— Hunter WebDev

236

С ES6 используйте оператор распространения ...:

DEMO

var arr = [23, 45, 12, 67];
arr = [34, ...arr]; // RESULT : [34,23, 45, 12, 67]

console.log(arr)


19
также создает новый массив, полезный для чистых функций
— devonj

Какое значение здесь имеет производительность? Это медленнее, чем использование unshift ()?
— Питер Т.

1
Конечно, это будет медленнее, поскольку это неизменный массив (создание нового массива). Если вы работаете с большим массивом или производительность является вашим первым требованием, рассмотрите возможность использования concatвместо этого.
— Abdennour TOUMI

производительность не важна в 2018 году, новые версии в браузере и узле получают одинаковую производительность
— stackdave

76

Еще один способ сделать это через concat

var arr = [1, 2, 3, 4, 5, 6, 7];
console.log([0].concat(arr));

Разница между concatи в unshiftтом, что concatвозвращает новый массив. Представление между ними можно найти здесь .

function fn_unshift() {
  arr.unshift(0);
  return arr;
}

function fn_concat_init() {
  return [0].concat(arr)
}

Вот результат теста

введите описание изображения здесь


Для вашего ответа было бы неплохо добавить сравнение производительности, помимо добавления ссылки.
— Иван Де Пас Сентено

Я только что получил, что jsPerf временно недоступен, пока мы работаем над выпуском v2. Пожалуйста, попробуйте позже по ссылке. Еще одна веская причина, чтобы включить результаты вместо ссылки на них.
— Тигр

Результат jsPrefunshift :: 25 510 ± 3,18% На 99% медленнее concat: 2 436 894 ± 3,39% быстрее
— Иллюминатор

В последнем Safari fn_unshift () работает быстрее.
— passatgt

В последнем Safari (v 10) fn_unshift () снова работает медленнее.
— rmcsharry

45

Быстрый Cheatsheet:

Термины shift / unshift и push / pop могут быть немного запутанными, по крайней мере, для людей, которые могут быть не знакомы с программированием на C.

Если вы не знакомы с жаргоном, вот быстрый перевод альтернативных терминов, который может быть легче запомнить:

* array_unshift()  -  (aka Prepend ;; InsertBefore ;; InsertAtBegin )     
* array_shift()    -  (aka UnPrepend ;; RemoveBefore  ;; RemoveFromBegin )

* array_push()     -  (aka Append ;; InsertAfter   ;; InsertAtEnd )     
* array_pop()      -  (aka UnAppend ;; RemoveAfter   ;; RemoveFromEnd ) 

20

у вас есть массив: var arr = [23, 45, 12, 67];

Чтобы добавить элемент в начало, вы хотите использовать splice:

var arr = [23, 45, 12, 67];
arr.splice(0, 0, 34)
console.log(arr);


arr.splice (0, длина луча, 34);
— Лиор Элром

1
@LiorElrom что делает твой фрагмент?
— Янус Троелсен

@poushy это специфично для браузера, в Firefox 54 работает на unshift50% быстрее (но в основном более читабельно)
— icl7126

@poushy Больше нет. Намного медленнее.
— Андрей

17

Без мутирования

На самом деле, все unshift/ pushи shift/ pop мутировать массив.

unshift/ pushДобавить элемент к существовавшему массиву из начала / конца и shift/pop удалить элемент из начала / конца массива.

Но есть несколько способов добавить элементы в массив без мутации. В результате получается новый массив, для добавления в конец массива используйте следующий код:

const originArray = ['one', 'two', 'three'];
const newItem = 4;

const newArray = originArray.concat(newItem); // ES5
const newArray2 = [...originArray, newItem]; // ES6+

Для добавления в начало оригинального массива используйте код ниже:

const originArray = ['one', 'two', 'three'];
const newItem = 0;

const newArray = (originArray.slice().reverse().concat(newItem)).reverse(); // ES5
const newArray2 = [newItem, ...originArray]; // ES6+

Вышеописанным способом вы добавляете в начало / конец массива без мутации.


Я просто поставил sliceфункцию в конце, originArrayчтобы предотвратить ее изменчивость.
— Ахмад Хани

1
Потрясающие! Когда дело доходит до (Redux) государственного управления ... этот ответ драгоценен!
— Педро Феррейра

1
Это правильный путь!
— ммм

10

Использование ES6 деструктуризации: (избегая мутации из исходного массива)

const newArr = [item, ...oldArr]


8

Если вам нужно постоянно вставлять элемент в начале массива, быстрее использовать pushоператоры с последующим вызовом reverseвместо того, чтобы вызывать unshiftвсе время.

Контрольный тест: http://jsben.ch/kLIYf


1
Примечание: исходный массив должен быть пустым.
— 192kb

5

Используя, spliceмы вставляем элемент в массив в начале:

arrName.splice( 0, 0, 'newName1' );

Это правильный ответ. Спасибо Срикрушна
— Хан Чан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.