Переместить элементы массива в другой массив
у меня есть массив JavaScript dataArray который я хочу вставить в новый массив newArray. Только я не хочу newArray[0] на dataArray. Я хочу вставить все элементы в новый массив:
var newArray = [];
newArray.pushValues(dataArray1);
newArray.pushValues(dataArray2);
// ...
или еще лучше:
var newArray = new Array (
dataArray1.values(),
dataArray2.values(),
// ... where values() (or something equivalent) would push the individual values into the array, rather than the array itself
);
Итак, теперь новый массив, содержащий все значения отдельных массивов данных. Есть ли какая-то стенография, как pushValues доступно, поэтому мне не нужно перебирать каждого человека dataArray, добавляя элементы по одному?
15 ответов:
использовать функция concat, например:
var arrayA = [1, 2]; var arrayB = [3, 4]; var newArray = arrayA.concat(arrayB);значение
newArrayбудет[1, 2, 3, 4](arrayAиarrayBостаются неизменными;concatсоздает и возвращает новый массив для результата).
при условии, что ваши массивы не огромны (см. предостережение ниже), вы можете использовать
push()метод массива, к которому вы хотите присвоить значения.push()может иметь несколько параметров, так что вы можете использоватьapply()метод для передачи массива значений, которые будут переданы в виде списка параметров функции. Это имеет преимущество перед использованиемconcat()для добавления элементов в массив на месте, а не создавать новый массив.однако, похоже, что для больших массивов (порядка 100 000 членов или более),этот трюк может не. Для таких массивов использование цикла является лучшим подходом. Смотрите https://stackoverflow.com/a/17368101/96100 подробнее.
var newArray = []; newArray.push.apply(newArray, dataArray1); newArray.push.apply(newArray, dataArray2);вы, возможно, захотите, чтобы обобщить эту функцию:
function pushArray(arr, arr2) { arr.push.apply(arr, arr2); }... или добавьте его в С:
Array.prototype.pushArray = function(arr) { this.push.apply(this, arr); }; var newArray = []; newArray.pushArray(dataArray1); newArray.pushArray(dataArray2);... или эмулировать оригинал
push()способ позволяет несколько параметров, используя тот факт, чтоconcat(), какpush(), позволяет несколько параметров:Array.prototype.pushArray = function() { this.push.apply(this, this.concat.apply([], arguments)); }; var newArray = []; newArray.pushArray(dataArray1, dataArray2);вот циклическая версия последнего примера, подходящая для больших массивов и всех основных браузеров, включая IE
Array.prototype.pushArray = function() { var toPush = this.concat.apply([], arguments); for (var i = 0, len = toPush.length; i < len; ++i) { this.push(toPush[i]); } };
Я добавлю еще один" будущий " ответ
в ECMAScript 6, Вы можете использовать распространение оператор:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1.push(...arr2);оператор распространения еще не включен во все основные браузеры. Для текущей совместимости см. Это (постоянно обновляется)таблица совместимости.
вы можете, однако, использовать оператор spread с Бабель.js.
edit:
см. ответ Джека Гиффина ниже для получения дополнительных комментариев спектакль. Кажется, что concat все еще лучше и быстрее, чем оператор распространения.
нашел элегантный способ от MDN
var vegetables = ['parsnip', 'potato']; var moreVegs = ['celery', 'beetroot']; // Merge the second array into the first one // Equivalent to vegetables.push('celery', 'beetroot'); Array.prototype.push.apply(vegetables, moreVegs); console.log(vegetables); // ['parsnip', 'potato', 'celery', 'beetroot']или вы можете использовать
spread operatorособенность ES6:let fruits = [ 'apple', 'banana']; const moreFruits = [ 'orange', 'plum' ]; fruits.push(...moreFruits); // ["apple", "banana", "orange", "plum"]
var a=new Array('a','b','c'); var b=new Array('d','e','f'); var d=new Array('x','y','z'); var c=a.concat(b,d)это решает вашу проблему ?
мне кажется самым простым следующее:
var newArray = dataArray1.slice(); newArray.push.apply(newArray, dataArray2);поскольку "push" принимает переменное количество аргументов, вы можете использовать
applyметодpushфункция для нажатия всех элементов другого массива. Он строит вызов push с использованием его первого аргумента ("newArray" здесь) как " это " и элементы массива в качестве остальных аргументов.The
sliceв первом операторе получает копию первого массива, поэтому вы не изменяете оно.обновление если вы используете версию javascript с доступным слайсом, вы можете упростить
pushвыражение:newArray.push(...dataArray2)
есть ряд ответов, говорящих о массив.прототип.толкать.применить. Вот наглядный пример:
var dataArray1 = [1, 2]; var dataArray2 = [3, 4, 5]; var newArray = [ ]; Array.prototype.push.apply(newArray, dataArray1); // newArray = [1, 2] Array.prototype.push.apply(newArray, dataArray2); // newArray = [1, 2, 3, 4, 5] console.log(JSON.stringify(newArray)); // Outputs: [1, 2, 3, 4, 5]Если у вас есть синтаксис ES6:
var dataArray1 = [1, 2]; var dataArray2 = [3, 4, 5]; var newArray = [ ]; newArray.push(...dataArray1); // newArray = [1, 2] newArray.push(...dataArray2); // newArray = [1, 2, 3, 4, 5] console.log(JSON.stringify(newArray)); // Outputs: [1, 2, 3, 4, 5]
С JavaScript ES6, вы можете использовать... оператор как оператор распространения, который по существу преобразует массив в значения. Затем, вы можете сделать что-то вроде этого:
var myArray = [1,2,3,4,5]; var moreData = [6,7,8,9,10]; myArray = [ ...myArray, ...moreData, ];хотя синтаксис лаконичен, Я не знаю, как это работает внутри и каковы последствия для производительности больших массивов.
функция ниже не имеет проблемы с длиной массивов и выполняет лучше, чем все предлагаемые решения:
function pushArray(list, other) { var len = other.length; var start = list.length; list.length = start + len; for (var i = 0; i < len; i++ , start++) { list[start] = other[i]; } }к сожалению, jspref отказывается принимать мои представления, так что вот они результаты с помощью бенчмарка.js
Name | ops/sec | ± % | runs sampled for loop and push | 177506 | 0.92 | 63 Push Apply | 234280 | 0.77 | 66 spread operator | 259725 | 0.40 | 67 set length and for loop | 284223 | 0.41 | 66здесь
для петли и нажмите:
for (var i = 0, l = source.length; i < l; i++) { target.push(source[i]); }Нажимаем Применить:
target.push.apply(target, source);распространение оператор:
target.push(...source);и, наконец, "установить длину и для цикла" является выше функция
вот путь ES6
var newArray = []; let dataArray1 = [1,2,3,4] let dataArray2 = [5,6,7,8] newArray = [...dataArray1, ...dataArray2] console.log(newArray)
Научные Исследования И Результаты
для фактов, a тест производительности в jsperf и проверка некоторых вещей в консоли выполняются. Для исследования, сайт irt.org используется. Ниже приведена коллекция всех этих источников, собранных вместе, а также пример функции внизу.
╔═══════════════╦══════╦═════════════════╦═══════════════╦═════════╦══════════╗ ║ Method ║Concat║slice&push.apply ║ push.apply x2 ║ ForLoop ║Spread ║ ╠═══════════════╬══════╬═════════════════╬═══════════════╬═════════╬══════════╣ ║ mOps/Sec ║179 ║104 ║ 76 ║ 81 ║28 ║ ╠═══════════════╬══════╬═════════════════╬═══════════════╬═════════╬══════════╣ ║ Sparse arrays ║YES! ║Only the sliced ║ no ║ Maybe2 ║no ║ ║ kept sparse ║ ║array (1st arg) ║ ║ ║ ║ ╠═══════════════╬══════╬═════════════════╬═══════════════╬═════════╬══════════╣ ║ Support ║MSIE 4║MSIE 5.5 ║ MSIE 5.5 ║ MSIE 4 ║Edge 12 ║ ║ (source) ║NNav 4║NNav 4.06 ║ NNav 4.06 ║ NNav 3 ║MSIENNav║ ╠═══════════════╬══════╬═════════════════╬═══════════════╬═════════╬══════════╣ ║Array-like acts║no ║Only the pushed ║ YES! ║ YES! ║If have ║ ║like an array ║ ║array (2nd arg) ║ ║ ║iterator1 ║ ╚═══════════════╩══════╩═════════════════╩═══════════════╩═════════╩══════════╝ 1 If the array-like object does not have a Symbol.iterator property, then trying to spread it will throw an exception. 2 Depends on the code. The following example code "YES" preserves sparseness.function mergeCopyTogether(inputOne, inputTwo){ var oneLen = inputOne.length, twoLen = inputTwo.length; var newArr = [], newLen = newArr.length = oneLen + twoLen; for (var i=0, tmp; i !== oneLen; ++i) { tmp = inputOne[i]; if (tmp !== undefined || inputOne.hasOwnProperty(i)) newArr[i] = tmp; } for (var i=0, tmp; i !== oneLen; ++i) { tmp = inputOne[i]; if (tmp !== undefined || inputOne.hasOwnProperty(i)) newArr[i] = tmp; } return newArr; }как видно выше, я бы сказал, что Concat-это почти всегда способ пойти как для производительности, так и для способности сохранить разреженность запасных массивов. Затем, для массивов-подобных (таких как DOMNodeLists like
document.body.children), Я бы рекомендовал использовать цикл for, потому что это как 2-й наиболее производительный, так и единственный другой метод, который сохраняет разреженные массивы. Ниже мы быстро перейдем к тому, что подразумевается под разреженными массивами и массивами-любит прояснять путаницу.Будущее
во-первых, некоторые люди могут подумать, что это случайность, и что поставщики браузеров в конечном итоге перейдут к оптимизации Матрица.прототип.нажмите, чтобы быть достаточно быстрым, чтобы бить массив.прототип.функция concat. Неправильно! Матрица.прототип.concat всегда будет быстрее (в принципе, по крайней мере), потому что это простая копия-N-вставка данных. Ниже приведена упрощенная наглядная схема того, как может выглядеть реализация 32-битного массива (обратите внимание, что реальные реализации намного сложнее)
Byte ║ Data here ═════╬═══════════ 0x00 ║ int nonNumericPropertiesLength = 0x00000000 0x01 ║ ibid 0x02 ║ ibid 0x03 ║ ibid 0x00 ║ int length = 0x00000001 0x01 ║ ibid 0x02 ║ ibid 0x03 ║ ibid 0x00 ║ int valueIndex = 0x00000000 0x01 ║ ibid 0x02 ║ ibid 0x03 ║ ibid 0x00 ║ int valueType = JS_PRIMITIVE_NUMBER 0x01 ║ ibid 0x02 ║ ibid 0x03 ║ ibid 0x00 ║ uintptr_t valuePointer = 0x38d9eb60 (or whereever it is in memory) 0x01 ║ ibid 0x02 ║ ibid 0x03 ║ ibidкак видно выше, все, что вам нужно сделать, чтобы скопировать что-то подобное, почти так же просто, как скопировать его байт для байт. с массивами.прототип.толкать.применять, это намного больше, чем просто копировать-вставлять данные. Этот." применить " должен проверить каждый индекс в массиве и преобразовать его в набор аргументов перед передачей его в массив.прототип.толкать. Затем, Массив.прототип.push должен дополнительно выделять больше памяти каждый раз, и (для некоторых реализаций браузера), возможно, даже пересчитать некоторые данные поиска позиции для разреженности.
альтернативный способ думать об этом заключается в следующем. Исходный массив один большая стопка бумаг, скрепленных вместе. Исходный массив два также является еще одной большой стопкой документов. Было бы быстрее для вас
- зайдите в магазин, купите достаточно бумаги, необходимой для копирования каждого исходного массива. Затем поместите каждый исходный массив стопок бумаги через копировальную машину и скрепите полученные две копии вместе.
- зайдите в магазин, купите достаточно бумаги для одной копии первого исходного массива. Затем скопируйте исходный массив на новую бумагу вручную, обеспечение заполнения любых пустых разреженных пятен. Затем вернитесь в магазин, купите достаточно бумаги для второго исходного массива. Затем пройдите через второй исходный массив и скопируйте его, не обеспечивая пустых пробелов в копии. Затем скрепите все скопированные бумаги вместе.
в приведенной выше аналогии опция #1 представляет массив.прототип.concat в то время как #2 представляет массив.прототип.толкать.применять. Давайте проверим это с помощью аналогичного JSperf, отличающегося только тем, что этот тестирует методы более разреженные массивы, а не сплошные массивы. Его можно найти здесь.
поэтому я останавливаюсь на том, что будущее производительности для этого конкретного случая использования лежит не в массиве.прототип.толчок, но скорее в массиве.прототип.функция concat.
пояснения
Запасные Массивы
когда некоторые элементы массива просто отсутствуют. Например:
// This is just as an example. In actual code, // do not mix different types like this. var mySparseArray = []; mySparseArray[0] = "foo"; mySparseArray[10] = undefined; mySparseArray[11] = {}; mySparseArray[12] = 10; mySparseArray[17] = "bar"; console.log("Length: ", mySparseArray.length); console.log("0 in it: ", 0 in mySparseArray); console.log("arr[0]: ", mySparseArray[0]); console.log("10 in it: ", 10 in mySparseArray); console.log("arr[10] ", mySparseArray[10]); console.log("20 in it: ", 20 in mySparseArray); console.log("arr[20]: ", mySparseArray[20]);кроме того, javascript позволяет вы легко инициализируете запасные массивы.
var mySparseArray = ["foo",,,,,,,,,,undefined,{},10,,,,,"bar"];Массив-Это Нравится
массив-подобный объект, который имеет по крайней мере
lengthсвойство, но не было инициализировано с помощьюnew Arrayили[]; например, ниже предметы классифицируются как массивов.{0: "foo", 1: "bar", length:2}document.body.childrennew Uint8Array(3)
- это похоже на массив, потому что, хотя это(N) (типизированный) массив, приведение его к массиву изменяет конструктор.
(function(){return arguments})()соблюдать что происходит с использованием метода, который принуждает array-likes в массивы, такие как slice.
var slice = Array.prototype.slice; console.log(slice.call({0: "foo", 1: "bar", length:2})); console.log(slice.call(document.body.children)); console.log(slice.call(new Uint8Array(3))); console.log(slice.call( function(){return arguments}() ));
- Примечание: это плохая практика, чтобы нарезать аргумент функции из-за производительности.
наблюдать, что происходит с помощью метода, который делает не принудительный массив-любит в массивы, такие как concat.
var empty = []; console.log(empty.concat({0: "foo", 1: "bar", length:2})); console.log(empty.concat(document.body.children)); console.log(empty.concat(new Uint8Array(3))); console.log(empty.concat( function(){return arguments}() ));
у нас есть два массива a и b. код, что сделал здесь массив A значение вставляется в массив b.
let a = [2, 4, 6, 8, 9, 15] function transform(a) { let b = ['4', '16', '64'] a.forEach(function(e) { b.push(e.toString()); }); return b; } transform(a) [ '4', '16', '64', '2', '4', '6', '8', '9', '15' ]
вместо функции push () используйте функцию concat для IE. например,
var a=a.concat(a,new Array('amin'));
Это рабочий код и он отлично работает:
var els = document.getElementsByTagName('input'), i; var invnum = new Array(); var k = els.length; for(i = 0; i < k; i++){invnum.push(new Array(els[i].id,els[i].value))}
Comments