Переместить элементы массива в другой массив



у меня есть массив 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, добавляя элементы по одному?

528   15  

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  ║MSIE NNav ║
╠═══════════════╬══════╬═════════════════╬═══════════════╬═════════╬══════════╣
║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. зайдите в магазин, купите достаточно бумаги, необходимой для копирования каждого исходного массива. Затем поместите каждый исходный массив стопок бумаги через копировальную машину и скрепите полученные две копии вместе.
  2. зайдите в магазин, купите достаточно бумаги для одной копии первого исходного массива. Затем скопируйте исходный массив на новую бумагу вручную, обеспечение заполнения любых пустых разреженных пятен. Затем вернитесь в магазин, купите достаточно бумаги для второго исходного массива. Затем пройдите через второй исходный массив и скопируйте его, не обеспечивая пустых пробелов в копии. Затем скрепите все скопированные бумаги вместе.

в приведенной выше аналогии опция #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.children
new 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))}

самое простое:

var newArray = dataArray1.slice(0);

Comments

    Ничего не найдено.