Jaki jest bardziej efektywny sposób wstawiania tablicy do innej tablicy.
a1 = [1,2,3,4,5];
a2 = [21,22];
newArray - a1.insertAt(2,a2) -> [1,2, 21,22, 3,4,5];
Iterowanie a2 za pomocą splice wygląda trochę fatalnie z punktu widzenia wydajności, jeśli tablica a2 jest duża.
Dzięki.
Odpowiedzi:
Możesz użyć w
splice
połączeniu z pewnymiapply
sztuczkami:a1 = [1,2,3,4,5]; a2 = [21,22]; a1.splice.apply(a1, [2, 0].concat(a2)); console.log(a1); // [1, 2, 21, 22, 3, 4, 5];
W ES2015 + możesz zamiast tego użyć operatora spreadu, aby uczynić to nieco ładniejszym
a1.splice(2, 0, ...a2);
źródło
apply
zgłosi wyjątek przepełnienia stosu . jsfiddle.net/DcHCY Dzieje się również w jsPerf Wierzę w FF i IE, próg wynosi około 500 tys.target.slice(0, insertIndex).concat(insertArr, target.slice(insertIndex));
jsperf.com/inserting-an-array-within-an-arrayMożesz to teraz zrobić, jeśli używasz ES2015 lub nowszego:
var a1 = [1,2,3,4,5]; var a2 = [21,22]; a1.splice(2, 0, ...a2); console.log(a1) // => [1,2,21,22,3,4,5]
Zapoznaj się z dokumentacją dotyczącą operatora (...) spreadu https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
źródło
Na początku było źle. Powinienem był użyć
concat()
zamiast tego.var a1 = [1,2,3,4,5], a2 = [21,22], startIndex = 0, insertionIndex = 2, result; result = a1.slice(startIndex, insertionIndex).concat(a2).concat(a1.slice(insertionIndex));
Przykład: http://jsfiddle.net/f3cae/1/
To wyrażenie używa
slice(0, 2)
[docs], aby zwrócić pierwsze dwa elementya1
(gdzie0
jest indeksem początkowym i2
jest elementem deleteCount, chociaża1
nie jest zmieniany).Wynik pośredni :
[1,2]
Następnie używa
concat(a2)
[docs], aby dołączyća2
na końcu[1,2]
.Wynik pośredni :
[1,2,21,22]
.Następnie
a1.slice(2)
wywoływana jest w końcowym.concat()
końcu tego wyrażenia, co sprowadza się do[1,2,21,22].concat(a1.slice(2))
.Wywołanie funkcji
slice(2)
, mające dodatni argument w postaci liczby całkowitej, zwróci wszystkie elementy po drugim elemencie, licząc według liczb naturalnych (tak jak w przypadku jest pięć elementów, więc[3,4,5]
zostanie zwrócona za1
). Innym sposobem na powiedzenie tego jest to, że argument indeksu pojedynczej liczby całkowitej wskazuje,a1.slice()
od której pozycji w tablicy należy rozpocząć zwracanie elementów (indeks 2 jest trzecim elementem).Wynik pośredni :
[1,2,21,22].concat([3,4,5])
Wreszcie druga
.concat()
dodaje[3,4,5]
na końcu[1,2,21,22]
.Wynik :
[1,2,21,22,3,4,5]
Zmiana może być kusząca
Array.prototype
, ale można po prostu rozszerzyć obiekt Array za pomocą dziedziczenia prototypowego i wstrzyknąć wspomniany nowy obiekt do swoich projektów.Jednak dla tych, którzy żyją na krawędzi ...
Przykład: http://jsfiddle.net/f3cae/2/
Array.prototype.injectArray = function( idx, arr ) { return this.slice( 0, idx ).concat( arr ).concat( this.slice( idx ) ); }; var a1 = [1,2,3,4,5]; var a2 = [21,22]; var result = a1.injectArray( 2, a2 );
źródło
Rozprzestrzenianie operatora umożliwia wyrażenie zostać rozszerzony w miejscach, w których oczekuje się wiele argumentów (dla połączeń Function) lub więcej elementów (na literałach tablicy).
a2 = [21,22]; a1 = [1,2,...a2,3,4,5];//...a2 is use of spread operator console.log(a1);
źródło
Istnieje kilka naprawdę twórczych odpowiedzi na to pytanie. Oto proste rozwiązanie dla tych, którzy dopiero zaczynają przygodę z tablicami. W razie potrzeby można go zmusić do pracy aż do przeglądarek zgodnych z ECMAScript 3.
Dowiedz się czegoś o łączeniu, zanim zaczniesz.
Mozilla Developer Network: Array.prototype.splice ()
Najpierw poznaj dwie ważne formy
.splice()
.let a1 = [1,2,3,4], a2 = [1,2];
Metoda 1) Usuń elementy x (deleteCount), zaczynając od żądanego indeksu.
let startIndex = 0, deleteCount = 2; a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]
Metoda 2) Usuń elementy po żądanym indeksie początkowym do końca tablicy.
a1.splice(2); // returns [3,4], a1 would be [1,2]
Używając
.splice()
, celem może być podzieleniea1
na układy głowy i ogona przy użyciu jednej z dwóch powyższych form.Korzystając z metody nr 1, zwracana wartość byłaby głową i
a1
końcem.let head = a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]
Teraz za jednym zamachem połącz głowę, ciało (
a2
) i ogonTym samym rozwiązanie to bardziej przypomina rzeczywisty świat niż jakiekolwiek inne prezentowane do tej pory. Czy nie to byś zrobił z Legosem? ;-) Oto funkcja wykonywana przy użyciu metody nr 2.
/** *@param target Array The array to be split up into a head and tail. *@param body Array The array to be inserted between the head and tail. *@param startIndex Integer Where to split the target array. */ function insertArray(target, body, startIndex) { let tail = target.splice(startIndex); // target is now [1,2] and the head return [].concat(target, body, tail); } let newArray = insertArray([1, 2, 3, 4], ["a", "b"], 2); // [1, 2, "a", "b", 3, 4]
Krótszy:
/** *@param target Array The array to be split up into a head and tail. *@param body Array The array to be inserted between the head and tail. *@param startIndex Integer Where to split the target array. */ function insertArray(target, body, startIndex) { return [].concat(target, body, target.splice(startIndex)); }
Bezpieczniej:
/** *@param target Array The array to be split up into a head and tail. *@param body Array The array to be inserted between the head and tail. *@param startIndex Integer Where to split the target array. *@throws Error The value for startIndex must fall between the first and last index, exclusive. */ function insertArray(target, body, startIndex) { const ARRAY_START = 0, ARRAY_END = target.length - 1, ARRAY_NEG_END = -1, START_INDEX_MAGNITUDE = Math.abs(startIndex); if (startIndex === ARRAY_START) { throw new Error("The value for startIndex cannot be zero (0)."); } if (startIndex === ARRAY_END || startIndex === ARRAY_NEG_END) { throw new Error("The startIndex cannot be equal to the last index in target, or -1."); } if (START_INDEX_MAGNITUDE >= ARRAY_END) { throw new Error("The absolute value of startIndex must be less than the last index."); } return [].concat(target, body, target.splice(startIndex)); }
Zalety tego rozwiązania to:
1) W rozwiązaniu dominuje proste założenie - wypełnij pustą tablicę.
2) Nazewnictwo głowy, ciała i ogona jest naturalne.
3) Brak podwójnego wywołania
.slice()
. Żadnego krojenia.4) Nie
.apply()
. Wysoce niepotrzebne.5) Unika się łączenia metod.
6) Działa w ECMAScript 3 i 5 po prostu używając
var
zamiastlet
lubconst
.** 7) Zapewnia, że będzie głowa i ogon do uderzenia w ciało, w przeciwieństwie do wielu innych przedstawionych rozwiązań. Jeśli dodajesz tablicę przed lub po granicach, powinieneś przynajmniej użyć
.concat()
!!!!Uwaga: użycie opearatora do rozprzestrzeniania
...
sprawia, że wszystko to jest znacznie łatwiejsze do wykonania.źródło
Chciałem znaleźć sposób, aby to zrobić
splice()
bez iteracji: http://jsfiddle.net/jfriend00/W9n27/ .a1 = [1,2,3,4,5]; a2 = [21,22]; a2.unshift(2, 0); // put first two params to splice onto front of array a1.splice.apply(a1, a2); // pass array as arguments parameter to splice console.log(a1); // [1, 2, 21, 22, 3, 4, 5];
W postaci funkcji ogólnego przeznaczenia:
function arrayInsertAt(destArray, pos, arrayToInsert) { var args = []; args.push(pos); // where to insert args.push(0); // nothing to remove args = args.concat(arrayToInsert); // add on array to insert destArray.splice.apply(destArray, args); // splice it in }
źródło
a2
tablicę, co prawdopodobnie jest całkiem niepożądane. Nie musisz też przechodzić do punktu, wArray.prototype
którym masz już funkcję wycinania naa1
luba2
.apply()
metody.Array.prototype.splice
vsa1.splice
:).concat
zwraca nową tablicę, nie modyfikuje istniejącej, jak npsplice
. Powinno byćargs = args.concat(arrayToInsert);
var a1 = [1,2,3,4,5]; var a2 = [21,22]; function injectAt(d, a1, a2) { for(var i=a1.length-1; i>=d; i--) { a1[i + a2.length] = a1[i]; } for(var i=0; i<a2.length; i++) { a1[i+d] = a2[i]; } } injectAt(2, a1, a2); alert(a1);
źródło
Oto moja wersja bez specjalnych sztuczek:
function insert_array(original_array, new_values, insert_index) { for (var i=0; i<new_values.length; i++) { original_array.splice((insert_index + i), 0, new_values[i]); } return original_array; }
źródło
.apply()
.Jeśli chcesz wstawić kolejną tablicę do tablicy bez tworzenia nowego, najprostszym sposobem jest użycie albo
push
lubunshift
zapply
Na przykład:
a1 = [1,2,3,4,5]; a2 = [21,22]; // Insert a1 at beginning of a2 a2.unshift.apply(a2,a1); // Insert a1 at end of a2 a2.push.apply(a2,a1);
To działa, ponieważ oba
push
iunshift
przyjmują zmienną liczbę argumentów. Bonus, możesz łatwo wybrać, z którego końca chcesz dołączyć tablicę!źródło
a1.concat(a2)
alboa2.concat(a1)
wymyśliłem coś łatwiejszego niż to, co sugerujesz. Jednak problem polega na wstawieniu tablicy między granicami tablicy, a nie wyłącznie na dodaniu tablicy na początku lub na końcu. ;-)Jak wspomniano w innym wątku, powyższe odpowiedzi nie będą działać w bardzo dużych tablicach (200K elementów). Zobacz alternatywną odpowiedź dotyczącą łączenia i ręcznego wypychania: https://stackoverflow.com/a/41465578/1038326
Array.prototype.spliceArray = function(index, insertedArray) { var postArray = this.splice(index); inPlacePush(this, insertedArray); inPlacePush(this, postArray); function inPlacePush(targetArray, pushedArray) { // Not using forEach for browser compatability var pushedArrayLength = pushedArray.length; for (var index = 0; index < pushedArrayLength; index++) { targetArray.push(pushedArray[index]); } } }
źródło