Come inserire un elemento in un array in un indice specifico (JavaScript)?


2932

Sto cercando un metodo di inserimento di array JavaScript, nello stile di:

arr.insert(index, item)

Preferibilmente in jQuery, ma qualsiasi implementazione JavaScript andrà bene a questo punto.


96
Nota che JQuery è una libreria di manipolazione DOM ed eventi, non un linguaggio a sé stante. Non ha nulla a che fare con la manipolazione di array.
Domino,

25
api.jquery.com/jQuery.inArray non ha nulla a che fare con il DOM o gli eventi. jQuery si è evoluto in un toolkit misto per lo sviluppo di JS nel browser, portando le persone ad aspettarsi che abbia un metodo per tutto.
Tim

4
@Tim, Ma non è ancora un linguaggio a sé stante (ci sono ancora alcune domande come "come sommare due numeri in jQuery" qui su SO)
Victor

3
@Victor No, e mai lo sarà. jQuery è stato utile e pertinente, ma ha avuto il suo momento.
Tim

1
Inoltre, vedi questo , per una sorpresa contorta (:
noobie,

Risposte:


4757

Quello che vuoi è la splicefunzione sull'oggetto array nativo.

arr.splice(index, 0, item);inserirà itemin arrcorrispondenza dell'indice specificato (cancellando 0oggetti prima, cioè, è solo un inserto).

In questo esempio creeremo un array e aggiungeremo un elemento ad esso nell'indice 2:

var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";

console.log(arr.join());
arr.splice(2, 0, "Lene");
console.log(arr.join());


168
Grazie, ho pensato di sentirmi stupido per averlo chiesto, ma ora che conosco la risposta non lo so! Perché mai hanno deciso di chiamarlo giuntura quando un termine più ricercabile era di uso comune per la stessa funzione ?!
tags2k,

83
@ tags2k: perché la funzione fa molto di più che inserire elementi e il suo nome è già stato stabilito in perl?
Christoph,


55
La giunzione può essere inserita, ma altrettanto spesso no . Ad esempio: arr.splice(2,3)rimuoverà 3 elementi a partire dall'indice 2. Senza passare il 3 ° .... N ° parametro non viene inserito nulla. Quindi insert()neanche il nome rende giustizia.
EBarr

14
Penso che il termine "giuntura" abbia un senso. Splice significa unirsi o connettersi, anche per cambiare. Hai un array consolidato che ora stai "modificando" che implicherebbe l'aggiunta o la rimozione di elementi. Specificare da dove iniziare la matrice, quindi quanti vecchi elementi rimuovere (se presenti) e infine, facoltativamente, un elenco di nuovi elementi da aggiungere. Splice è anche un ottimo termine di fantascienza ovviamente.
Jakub Keller,

285

È possibile implementare il Array.insertmetodo in questo modo:

Array.prototype.insert = function ( index, item ) {
    this.splice( index, 0, item );
};

Quindi puoi usarlo come:

var arr = [ 'A', 'B', 'D', 'E' ];
arr.insert(2, 'C');

// => arr == [ 'A', 'B', 'C', 'D', 'E' ]

9
Per inserire più elementi è possibile utilizzareArray.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); }
Ryan Smith,

7
Il problema con l'aggiunta di cose all'array è che la funzione verrà visualizzata come elemento quando lo fai per (i in arr) {...}
rep_movsd

7
Ma tieni presente che non è consigliabile estendere i tipi nativi poiché potrebbe interferire con altri codici o funzionalità future.
Marsze,

17
Non modificare oggetti che non possiedi
Luis Cabrera Benito,

4
Non modificare i prototipi
satya164,

141

Oltre alla giunzione, è possibile utilizzare questo approccio che non modificherà l'array originale, ma creerà un nuovo array con l'elemento aggiunto. Di solito dovresti evitare la mutazione quando possibile. Sto usando l'operatore di diffusione ES6 qui.

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, newItem) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted item
  newItem,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10)

console.log(result)
// [1, 10, 2, 3, 4, 5]

Questo può essere usato per aggiungere più di un articolo modificando un po 'la funzione per utilizzare l'operatore di riposo per i nuovi articoli e diffonderlo anche nel risultato restituito

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, ...newItems) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted items
  ...newItems,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10, 20)

console.log(result)
// [1, 10, 20, 2, 3, 4, 5]


1
È un buon modo sicuro per farlo? Chiedo perché questo sembra così elegante e conciso, ma nessun'altra risposta tocca questo. Molti di loro modificano l'oggetto prototipo!
Harsh Kanchina,

5
@HarshKanchina Questo è probabilmente perché la maggior parte delle risposte sono pre ES6, ma questo approccio è molto comune ora dalla mia esperienza
gafi

77

insertMetodi di array personalizzati

1. Con argomenti multipli e supporto per il concatenamento

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    this.splice.apply(this, [index, 0].concat(
        Array.prototype.slice.call(arguments, 1)));
    return this;
};

Può inserire più elementi (come splicefa nativo ) e supporta il concatenamento:

["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]

2. Con argomenti di tipo array che uniscono e concatenano il supporto

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    index = Math.min(index, this.length);
    arguments.length > 1
        && this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
        && this.insert.apply(this, arguments);
    return this;
};

Può unire gli array dagli argomenti con l'array specificato e supporta anche il concatenamento:

["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"

DEMO: http://jsfiddle.net/UPphH/


Esiste un modo compatto per far sì che questa versione unisca anche un array quando ne trova uno negli argomenti?
Nolo,

Non capisco il primo risultato ["b", "X", "Y", "Z", "c"]. Perché non è "d"incluso? Mi sembra che se si inserisce 6 come secondo parametro di slice()e vi sono 6 elementi nell'array a partire dall'indice specificato, è necessario ottenere tutti e 6 gli elementi nel valore restituito. (Il documento dice howManyper quel parametro.) Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Alexis Wilke,

In realtà, se uso un indice di 3 o più, non ottengo nulla nell'output (caso 1., FireFox) ["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3);=>[ ]
Alexis Wilke,

@AlexisWilke Nel primo esempio ho usato il slicemetodo e non splice, a cui ti riferisci nel commento. Il secondo parametro di slice(denominato end) è un indice a base zero in corrispondenza del quale terminare l'estrazione. sliceestrae fino a ma non compresoend . Quindi dopo insertche hai ["a", "b", "X", "Y", "Z", "c", "d"], da cui sliceestrae elementi con indici da 1fino a 6, cioè da "b"a "d"ma non inclusi "d". Ha senso?
VisioN,

41

Se vuoi inserire più elementi contemporaneamente in un array, dai un'occhiata a questa risposta di Stack Overflow: un modo migliore per unire un array in un array in javascript

Anche qui ci sono alcune funzioni per illustrare entrambi gli esempi:

function insertAt(array, index) {
    var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
    return insertArrayAt(array, index, arrayToInsert);
}

function insertArrayAt(array, index, arrayToInsert) {
    Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
    return array;
}

Finalmente ecco un jsFiddle in modo da poterlo vedere da soli: http://jsfiddle.net/luisperezphd/Wc8aS/

Ed è così che usi le funzioni:

// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");

// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);

1
InsertAt () non farebbe meglio a chiamare insertArrayAt () dopo aver creato un arrayToInsert a elemento singolo? Ciò evita la ripetizione di codice identico.
Matt Sach,

1
questo è un ottimo esempio di quando usare 'apply'
CRice

Ho aggiunto un parametro removeCount a questo metodo per sfruttare la capacità di splice di rimuovere anche gli elementi in quell'indice: Array.prototype.splice.apply (array, [index, removeCount || 0] .concat (arrayToInsert));
CRice

23

Per una corretta programmazione funzionale e scopi di concatenamento Array.prototype.insert()è essenziale un'invenzione di . In realtà la giuntura avrebbe potuto essere perfetta se avesse restituito la matrice mutata invece di una matrice vuota totalmente priva di significato. Quindi eccolo qui

Array.prototype.insert = function(i,...rest){
  this.splice(i,0,...rest)
  return this
}

var a = [3,4,8,9];
document.write("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");

Bene ok quanto sopra con Array.prototype.splice()quello che muta l'array originale e alcuni potrebbero lamentarsi come "non dovresti modificare ciò che non ti appartiene" e questo potrebbe rivelarsi giusto. Quindi per il benessere pubblico vorrei dare un altro Array.prototype.insert()che non muta l'array originale. Eccolo;

Array.prototype.insert = function(i,...rest){
  return this.slice(0,i).concat(rest,this.slice(i));
}

var a = [3,4,8,9],
    b = a.insert(2,5,6,7);
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));


2
"un array vuoto totalmente privo di significato" - restituisce un array vuoto solo quando il secondo parametro è 0. Se è maggiore di 0, restituisce gli elementi rimossi dall'array. Dato che stai aggiungendo a un prototipo e splicemuta l'array originale, non credo che la "corretta programmazione funzionale" appartenga ovunque nelle vicinanze di splice.
chrisbajorin,

Stiamo parlando di insert qui e il secondo parametro di Array.prototype.splice () deve essere zero. E ciò che restituisce non ha altro significato se non "non ho cancellato nulla" e dal momento che lo usiamo per inserire un articolo abbiamo già quelle informazioni. Se non si desidera modificare l'array originale, è possibile fare lo stesso con due operazioni Array.prototype.slice () e una Array.prototype.concat (). Tocca a voi.
Redu,

1
La tua seconda implementazione è la più pulita di tutta questa pagina e hai zero voti. Per favore prendi il mio e continua il buon lavoro. (dovresti semplicemente evitare di mutare il prototipo ma lo sai già)
NiKo

1
Penso che valga la pena ricordare che il parametro restante è il nuovo ECMA 6 ( developer.mozilla.org/en/docs/Web/JavaScript/Reference/… )
Geza Turi,

18

Ti consiglio di usare JavaScript puro in questo caso, inoltre non esiste un metodo di inserimento in JavaScript, ma abbiamo un metodo che è un metodo Array integrato che fa il lavoro per te, si chiama splice ...

Vediamo cos'è splice () ...

Il metodo splice () modifica il contenuto di un array rimuovendo elementi esistenti e / o aggiungendo nuovi elementi.

OK, immagina di avere questo array qui sotto:

const arr = [1, 2, 3, 4, 5];

Possiamo rimuovere in 3questo modo:

arr.splice(arr.indexOf(3), 1);

Restituirà 3, ma se controlliamo arr ora, abbiamo:

[1, 2, 4, 5]

Fin qui tutto bene, ma come possiamo aggiungere un nuovo elemento all'array usando splice? Rimettiamo 3 in arr ...

arr.splice(2, 0, 3);

Vediamo cosa abbiamo fatto ...

Usiamo di nuovo splice , ma questa volta per il secondo argomento, passiamo 0 , significa che non vogliamo eliminare alcun elemento, ma allo stesso tempo, aggiungiamo il terzo argomento che è 3 che verrà aggiunto al secondo indice ...

Dovresti essere consapevole del fatto che possiamo eliminare e aggiungere contemporaneamente, ad esempio ora possiamo fare:

arr.splice(2, 2, 3);

Che eliminerà 2 elementi all'indice 2, quindi aggiungerà 3 all'indice 2 e il risultato sarà:

[1, 2, 3, 5];

Questo mostra come funziona ogni elemento nella giunzione:

array.splice (start, deleteCount, item1, item2, item3 ...)


13

Aggiungi elemento singolo a un indice specifico

//Append at specific position(here at index 1)
arrName.splice(1, 0,'newName1');
//1: index number, 0: number of element to remove, newName1: new element


//Append at specific position (here at index 3)
arrName[3] = 'newName1';

Aggiungi più elementi a un indice specifico

//Append from index number 1
arrName.splice(1, 0,'newElemenet1', 'newElemenet2', 'newElemenet3');
//1: index number from where append start, 
//0: number of element to remove, 
//newElemenet1,2,3: new elements

8
Vale la pena notare che arrName [3] non viene aggiunto, ma ignora.
sfratini

Aggiunge l'elemento all'array esistente non over ride, Ex: let arrName = ['xxx', 'yyy', 'zzz']; arrName.splice (1, 0, 'aaa', 'bbb', 'ccc'); dopo aver stampato arrName
Srikrushna,

Se arrName ha più di 3 elementi, stai sovrascrivendo il 3 °, non aggiungendo. O lo sto guardando nel modo sbagliato?
sfratini,

Se inseriamo un elemento nel mezzo, sposta l'elemento successivo non in eccesso. Si prega di specificare il problema, di cosa hai bisogno. Prendi un array (esempio) e ciò di cui hai bisogno sull'output. per favore commentami
Srikrushna,

1
@Srikrushna arrName[3] = 'newName1';aggiungerà se l'array ha solo 3 elementi. Se è presente un elemento nell'indice 3, questo verrà sostituito. Se vuoi aggiungere alla fine, è meglio usarearrName.push('newName1');
timore

6

Un'altra possibile soluzione, con l'utilizzo di Array#reduce.

var arr = ["apple", "orange", "raspberry"],
    arr2 = [1, 2, 4];

function insert(arr, item, index) {
    arr = arr.reduce(function(s, a, i) {
      i == index ? s.push(item, a) : s.push(a);
      return s;
    }, []);   
    console.log(arr);
}

insert(arr, "banana", 1);
insert(arr2, 3, 2);


6

Ecco due modi:

const array = [ 'My', 'name', 'Hamza' ];

array.splice(2, 0, 'is');

console.log("Method 1 : ", array.join(" "));

O

Array.prototype.insert = function ( index, item ) {
    this.splice( index, 0, item );
};

const array = [ 'My', 'name', 'Hamza' ];
array.insert(2, 'is');

console.log("Method 2 : ", array.join(" "));


4

Anche se è già stata data una risposta, sto aggiungendo questa nota per un approccio alternativo.

Volevo posizionare un numero noto di elementi in un array, in posizioni specifiche, poiché escono da un "array associativo" (cioè un oggetto) che per definizione non è garantito che sia in un ordine ordinato. Volevo che l'array risultante fosse un array di oggetti, ma gli oggetti fossero in un ordine specifico nell'array poiché un array garantisce il loro ordine. Quindi l'ho fatto.

Innanzitutto l'oggetto sorgente, una stringa JSONB recuperata da PostgreSQL. Volevo ordinarlo in base alla proprietà "order" in ogni oggetto figlio.

var jsonb_str = '{"one": {"abbr": "", "order": 3}, "two": {"abbr": "", "order": 4}, "three": {"abbr": "", "order": 5}, "initialize": {"abbr": "init", "order": 1}, "start": {"abbr": "", "order": 2}}';

var jsonb_obj = JSON.parse(jsonb_str);

Poiché il numero di nodi nell'oggetto è noto, per prima cosa creo un array con la lunghezza specificata:

var obj_length = Object.keys(jsonb_obj).length;
var sorted_array = new Array(obj_length);

E quindi iterare l'oggetto, posizionando gli oggetti temporanei appena creati nelle posizioni desiderate dell'array senza realmente aver luogo alcun "ordinamento".

for (var key of Object.keys(jsonb_obj)) {
  var tobj = {};
  tobj[key] = jsonb_obj[key].abbr;

  var position = jsonb_obj[key].order - 1;
  sorted_array[position] = tobj;
}

console.dir(sorted_array);

3

Chiunque abbia ancora problemi con questo e abbia provato tutte le opzioni sopra e non l'abbia mai ottenuto. Sto condividendo la mia soluzione, questo è per prendere in considerazione che non vuoi dichiarare esplicitamente le proprietà del tuo oggetto rispetto alla matrice.

function isIdentical(left, right){
    return JSON.stringify(left) === JSON.stringify(right);
}

function contains(array, obj){
    let count = 0;
    array.map((cur) => {
          if(this.isIdentical(cur, obj)) count++;
    });
    return count > 0;
}

Questa è una combinazione di iterare l'array di riferimento e confrontarlo con l'oggetto che si desidera verificare, convertirli entrambi in una stringa e quindi iterare se corrisponde. Quindi puoi solo contare. Questo può essere migliorato, ma è qui che mi sono sistemato. Spero che sia di aiuto.


3

Approfittando del metodo di riduzione come segue:

function insert(arr, val, index) {
    return index >= arr.length 
        ? arr.concat(val)
        : arr.reduce((prev, x, i) => prev.concat(i === index ? [val, x] : x), []);
}

Quindi in questo modo possiamo restituire un nuovo array (sarà un modo funzionale interessante - molto meglio dell'uso push o splice) con l'elemento inserito all'indice e se l'indice è maggiore della lunghezza dell'array verrà inserito alla fine.


3

Array#splice()è la strada da percorrere, a meno che tu non voglia davvero evitare di mutare l'array. Dati 2 array arr1e arr2, ecco come inserire il contenuto arr2in arr1dopo il primo elemento:

const arr1 = ['a', 'd', 'e'];
const arr2 = ['b', 'c'];

arr1.splice(1, 0, ...arr2); // arr1 now contains ['a', 'b', 'c', 'd', 'e']

console.log(arr1)

Se sei preoccupato di mutare l'array (ad esempio, se usi Immutable.js), puoi invece usare slice(), da non confondere con splice()a 'p'.

const arr3 = [...arr1.slice(0, 1), ...arr2, ...arr1.slice(1)];

2

Ho provato questo e funziona benissimo!

var initialArr = ["India","China","Japan","USA"];
initialArr.splice(index, 0, item);

Indice è la posizione in cui si desidera inserire o eliminare l'elemento. 0 vale a dire che il secondo parametro definisce il numero di elementi dall'indice da rimuovere. Sono le nuove voci che si desidera creare nella matrice. Può essere uno o più di uno.

initialArr.splice(2, 0, "Nigeria");
initialArr.splice(2, 0, "Australia","UK");

4
copia semplicemente incollata la risposta sopra. questo non aggiunge alcun valore alla domanda. o aggiungi una nuova risposta o un commento su esistente. per favore prova a contribuire con qualcosa di nuovo. non vogliamo rovinare questa comunità
hannad rehman,

1

Ecco una funzione funzionante che utilizzo in una mia applicazione.

Questo controlla se l'oggetto esce

let ifExist = (item, strings = [ '' ], position = 0) => {
     // output into an array with empty string. Important just in case their is no item. 
    let output = [ '' ];
    // check to see if the item that will be positioned exist.
    if (item) {
        // output should equal to array of strings. 
        output = strings;
       // use splice in order to break the array. 
       // use positition param to state where to put the item
       // and 0 is to not replace an index. Item is the actual item we are placing at the prescribed position. 
        output.splice(position, 0, item);
    }
    //empty string is so we do not concatenate with comma or anything else. 
    return output.join("");
};

E poi lo chiamo di seguito.

ifExist("friends", [ ' ( ', ' )' ], 1)}  // output: ( friends )
ifExist("friends", [ ' - '], 1)}  // output:  - friends 
ifExist("friends", [ ':'], 0)}  // output:   friends: 

1

Un po 'più vecchio, ma devo concordare con Redu sopra perché splice ha sicuramente un'interfaccia un po' confusa. E la risposta data da cdbajorin che "restituisce un array vuoto solo quando il secondo parametro è 0. Se è maggiore di 0, restituisce gli elementi rimossi dall'array" sta dimostrando il punto, sebbene accurato. L'intento della funzione è di giuntare o come detto in precedenza da Jakob Keller, "di unirsi o connettersi, anche per cambiare. Hai un array consolidato che stai cambiando che implicherebbe l'aggiunta o la rimozione di elementi ...." Dato che, il il valore di ritorno degli eventuali elementi che sono stati rimossi è nella migliore delle ipotesi scomodo. E concordo al 100% che questo metodo avrebbe potuto essere più adatto al concatenamento se avesse restituito ciò che sembra naturale, un nuovo array con gli elementi giuntati aggiunti. Quindi potresti fare cose come ["19", "17"]. Splice (1,0, "18"). Join ("...") o qualunque cosa ti piaccia con l'array restituito. Il fatto che restituisca ciò che è stato rimosso è solo un po 'senza senso IMHO. Se l'intenzione del metodo era di "ritagliare un insieme di elementi" e quello era solo l'intento, forse. Sembra che se non sapessi già cosa tagliare, probabilmente ho poche ragioni per ritagliarli, no? Sarebbe meglio se si comportasse come concat, map, ridurre, slice, ecc. Dove un nuovo array viene creato dall'array esistente piuttosto che mutare l'array esistente. Questi sono tutti incatenabili e questo è un problema significativo. È piuttosto comune alla manipolazione di array di catene. Sembra che la lingua debba andare in una direzione o nell'altra e cercare di attenersi il più possibile. Essendo Javascript funzionale e meno dichiarativo, sembra solo una strana deviazione dalla norma.


-2

Prestazione

Oggi (2020.04.24) eseguo test per soluzioni scelte per array grandi e piccoli. Li ho testati su MacO High Sierra 10.13.6 su Chrome 81.0, Safari 13.1, Firefox 75.0.

conclusioni

Per tutti i browser

  • sorprendentemente per le piccole matrici le soluzioni non sul posto basate su slicee reduce(D, E, F) sono in genere 10x-100x più veloci delle soluzioni sul posto
  • per array di grandi dimensioni le soluzioni basate sul posto basate su splice(AI, BI, CI) sono state le più veloci (a volte ~ 100x - ma dipende dalle dimensioni dell'array)
  • per array di piccole dimensioni la soluzione BI era più lenta
  • per array di grandi dimensioni la soluzione E è stata la più lenta

inserisci qui la descrizione dell'immagine

Dettagli

I test sono stati divisi in due gruppi: soluzioni sul posto (AI, BI, CI) e soluzioni non sul posto (D, E, F) e sono state eseguite per due casi

  • prova l'array con 10 elementi: puoi eseguirlo QUI
  • test per array con 1.000.000 di elementi: è possibile eseguirlo QUI

Il codice testato è presentato nello snippet di seguito

Di seguito sono riportati i risultati di esempio per array di piccole dimensioni su Chrome

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.