Как я могу добавить новые элементы массива в начале массива в 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.