Pytanie Jak wstawić element do tablicy w określonym indeksie?


Szukam metody wstawiania tablicy JavaScript w stylu:

arr.insert(index, item)

Najlepiej w jQuery, ale jakakolwiek implementacja JavaScripta będzie w tym momencie robić.


2081
2018-02-25 14:29


pochodzenie


Zauważ, że JQuery jest biblioteką manipulacji DOM i zdarzeń, a nie własnym językiem. Nie ma to nic wspólnego z manipulacją tablicą. - Jacque Goupil
api.jquery.com/jQuery.inArray nie ma nic wspólnego z DOMem ani wydarzeniami. jQuery przekształciło się w mieszany zestaw narzędzi do tworzenia JS w przeglądarce, co prowadzi do tego, że ludzie oczekują, że będzie dysponował metodą na wszystko. - Tim
@Tim, Ale nadal nie jest to język własny (wciąż jest kilka pytań typu "jak sumować dwie liczby w jQuery" tutaj na SO) - Victor
@Victor Nie, i nigdy nie będzie. jQuery był użyteczny i trafny, ale miał swój dzień. - Tim


Odpowiedzi:


To, czego chcesz, to splice funkcja na rodzimym obiekcie tablicy.

arr.splice(index, 0, item); wstawi item w arr pod określonym indeksem (usuwanie 0 rzeczy najpierw, to jest po prostu wstawka).

W tym przykładzie utworzymy tablicę i dodamy do niej element do indeksu 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());


3447
2018-02-25 14:32



Dzięki, pomyślałem, że będę głupio o to pytać, ale teraz, gdy znam odpowiedź, której nie znam! Dlaczego, u licha, zdecydowali się nazywać to splice, gdy bardziej wyszukiwalny termin był powszechnie używany dla tej samej funkcji ?! - tags2k
@ tags2k: ponieważ funkcja robi więcej niż wstawianie elementów, a nazwa została już ustalona w Perlu? - Christoph
doc: developer.mozilla.org/en/JavaScript/Guide/... - Dingo
Splatać mogą wstawić, ale równie często nie. Na przykład: arr.splice(2,3) usunie 3 elementy zaczynające się od indeksu 2. Bez podania 3. .... Nth parametry nic nie jest wstawiane. Więc imię insert() nie czyni tego również sprawiedliwością. - EBarr
Myślę, że termin "splice" ma sens. Splice oznaczają łączenie się lub łączenie, także w celu zmiany. Masz ustaloną tablicę, którą teraz "zmieniasz", co wiązałoby się z dodawaniem lub usuwaniem elementów. Określasz, w której części tablicy ma się zaczynać, ile starych elementów do usunięcia (jeśli istnieją) i na końcu, opcjonalnie listę nowych elementów do dodania. Splice to także świetny termin science-fiction. - Jakub Keller


Możesz wdrożyć Array.insert metoda, wykonując to:

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

Następnie możesz użyć go jak:

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

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

208
2017-10-03 14:26



Nie modyfikuj obiektów, które nie są Twoją własnością - Pavlo
Kto jest właścicielem Array? Ecita Script Comitee? Mam na myśli, jeśli zrobisz to z Object.defineProperty to może nie być tak źle, jak myśli Pavlo. - Capaj
Aby wstawić wiele przedmiotów, których możesz użyć Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); } - Ryan Smith
Problem z dodawaniem elementów do tablicy polega na tym, że funkcja będzie wyświetlana jako element, gdy wykonasz operację (w arr) {...} - rep_movsd
To, co mówi Pavlo, polega na tym, że - jeśli natywna metoda wstawiania jest zaimplementowana lub 2 lub więcej programistów w twojej firmie przyjdzie z tą samą ideą tworzenia wstawki dla obiektu tablicy, ale implementacja będzie inna ... Cóż, wpadłeś na pomysł. - Adam Moszczyński


Niestandardowa tablica insert metody

1. Z wieloma argumentami i łańcuchem wsparcia

/* 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;
};

Może wstawiać wiele elementów (jako natywne splice does) i obsługuje łańcuchowe:

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

2. Z argumentami typu tablicowego łączącymi i wspierającymi łańcuch

/* 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;
};

Może łączyć tablice z argumentami z podaną tablicą, a także obsługuje łańcuch:

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

PRÓBNY:  http://jsfiddle.net/UPphH/


64
2018-03-25 17:45



Czy istnieje zwarty sposób, aby ta wersja również scalała tablicę, gdy znajdzie jedną z argumentów? - Nolo
@Nolo Tak, można go znaleźć w zaktualizowanej odpowiedzi. - VisioN
Nie rozumiem pierwszego wyniku ["b", "X", "Y", "Z", "c"]. Dlaczego nie "d" w zestawie? Wydaje mi się, że jeśli umieścisz 6 jako drugi parametr slice() i jest 6 elementów w tablicy, począwszy od określonego indeksu, wtedy powinieneś otrzymać wszystkie 6 elementów w wartości zwracanej. (Doktor mówi howMany dla tego parametru.) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - Alexis Wilke
Właściwie, jeśli użyję indeksu 3 lub więcej, nie otrzymam niczego na wyjściu (przypadek 1., FireFox) ["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3); => [ ] - Alexis Wilke
@AlexisWilke W pierwszym przykładzie użyłem slice metoda i nie splice, do którego odnosisz się w komentarzu. Drugi parametr slice (o imieniu end) jest wskaźnik bazujący na zera, przy którym należy zakończyć ekstrakcję. slice wyodrębnia do, ale nie zawiera end. Stąd po insert ty masz ["a", "b", "X", "Y", "Z", "c", "d"], z którego slice wyodrębnia elementy z indeksów od 1 aż do 6, tj. od "b" do "d" ale nie wliczając "d". Czy jest sens? - VisioN


Oprócz splice, możesz użyć tej metody, która nie zmutuje oryginalnej tablicy, ale utworzy nową tablicę z dodanym elementem. Zazwyczaj unikaj mutacji. Używam tutaj operatora rozprzestrzeniania ES6.

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]

Można go użyć do dodania więcej niż jednego przedmiotu, nieco zmieniając funkcję, aby użyć operatora odpoczynku dla nowych elementów, i rozłożyć to również w zwracanym wyniku

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]


54
2017-07-04 09:18



dokładnie odpowiedź, której szukałem. Dziękuję Ci! - Alex Alexeev
Czy jest to dobry, bezpieczny sposób na zrobienie tego? Pytam, ponieważ wydaje się to tak eleganckie i zwięzłe, ale nie ma na nie innych odpowiedzi. Większość z nich modyfikuje obiekt prototypu! - Harsh Kanchina
@HarshKanchina Prawdopodobnie dlatego, że większość odpowiedzi to ES6, ale to podejście jest teraz bardzo popularne z mojego doświadczenia - Gaafar


Jeśli chcesz wstawić wiele elementów jednocześnie do tablicy, sprawdź tę odpowiedź przepełnienia stosu: Lepszy sposób na połączenie tablicy w javascript

Oto kilka funkcji ilustrujących oba przykłady:

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;
}

W końcu tutaj jest jsFiddle, więc możesz to dla siebie zobaczyć: http://jsfiddle.net/luisperezphd/Wc8aS/

I w ten sposób korzystasz z funkcji:

// 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);

33
2017-08-30 04:37



Czy metoda insertAt () lepiej nie wywoływałaby metody insertArrayAt () po utworzeniu pojedynczego elementu arrayToInsert? Dzięki temu unika się powtarzania identycznego kodu. - Matt Sach
jest to świetny przykład, kiedy użyć "zastosuj" - CRice
Dodałem parametr removeCount do tej metody, aby wykorzystać zdolność splicingu do usuwania elementów z tego indeksu: Array.prototype.splice.apply (array, [index, removeCount || 0] .concat (arrayToInsert)); - CRice


Do prawidłowego programowania funkcjonalnego i celów łańcuchowych wynalazek Array.prototype.insert() jest niezbędna. W rzeczywistości splice mogłyby być idealne, gdyby zwrócono zmutowaną tablicę zamiast całkowicie pustej tablicy. Więc oto idzie

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>");

No ok powyższe z Array.prototype.splice() jeden mutuje oryginalną tablicę, a niektórzy mogą narzekać: "nie powinieneś modyfikować tego, co nie należy do ciebie", a to może okazać się słuszne. Więc dla dobra publicznego chciałbym dać inny Array.prototype.insert() który nie mutuje oryginalnej tablicy. Oto jest;

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));


14
2018-05-13 23:22



"całkowicie pozbawiona znaczenia pusta tablica" - zwraca tylko pustą tablicę, gdy drugi parametr to 0. Jeśli jest większy niż 0, zwraca elementy usunięte z tablicy. Biorąc pod uwagę, że dodajesz do prototypu i splice mutuje oryginalną tablicę, nie sądzę, że "odpowiednie funkcjonalne programowanie" należy do dowolnego miejsca w pobliżu splice. - cdbajorin
Mówimy tutaj o wstawieniu, a drugi parametr Array.prototype.splice () musi wynosić zero. A to, co zwraca, nie ma innego znaczenia niż "nic nie usunąłem", a ponieważ używamy go do wstawienia przedmiotu, mamy już tę informację. Jeśli nie chcesz zmutować oryginalnej tablicy, możesz zrobić to samo z dwiema operacjami Array.prototype.slice () i jedną Array.prototype.concat (). To zależy od Ciebie. - Redu
Twoja druga implementacja jest najczystsza z całej tej strony i masz zero głosów. Proszę, weź moje i kontynuuj dobrą robotę. (powinieneś po prostu unikać mutowania prototypu, ale już to wiesz) - NiKo
Myślę, że warto wspomnieć, że parametr reszta to nowy ECMA 6th (developer.mozilla.org/en/docs/Web/JavaScript/Reference/... ) - Geza Turi


Polecam używanie czystego JavaScript w tym przypadku również nie ma metody wstawiania w JavaScript, ale mamy metodę, która jest wbudowany Array metoda, która wykonuje zadanie dla ciebie, to się nazywa splatać...

Zobaczmy, co jest splatać()...

Metoda splice () zmienia zawartość tablicy przez usunięcie   istniejące elementy i / lub dodawanie nowych elementów.

OK, wyobraź sobie, że mamy tę tablicę poniżej:

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

Możemy usunąć 3 lubię to:

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

Zwróci 3, ale jeśli sprawdzimy teraz arr, mamy:

[1, 2, 4, 5]

Jak dotąd, tak dobrze, ale w jaki sposób możemy dodać nowy element do tablicy za pomocą splice? Wróćmy 3 w arr ...

arr.splice(2, 0, 3);

Zobaczmy, co zrobiliśmy ...

Używamy splatać ponownie, ale tym razem dla drugiego argumentu, mijamy 0oznacza, że ​​nie chcemy usuwać żadnego elementu, ale jednocześnie dodajemy trzeci argument, który będzie 3, który zostanie dodany w drugim indeksie ...

Powinieneś być świadomy, że możemy kasować i Dodaj w tym samym czasie, na przykład teraz możemy zrobić:

arr.splice(2, 2, 3);

Który usunie 2 przedmioty w indeksie 2, a następnie dodaj 3 w indeksie 2 i wynik będzie:

[1, 2, 3, 5];

Pokazuje to, jak każdy element w splice działa:

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


7
2017-12-25 13:04





Inne możliwe rozwiązanie, z wykorzystaniem 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);


5
2018-04-05 17:06





Mimo że już zostało to udzielone, dodam tę uwagę do alternatywnego podejścia.

Chciałem umieścić znany numer elementów w tablicy, w określone pozycje, ponieważ pochodzą one z "tablicy asocjacyjnej" (tj. obiektu), która z definicji nie jest zagwarantowana w uporządkowanej kolejności. Chciałem, aby tablica wynikowa była tablicą obiektów, ale obiektów znajdujących się w określonej kolejności w tablicy, ponieważ tablica gwarantuje ich kolejność. Więc zrobiłem to.

Najpierw obiekt źródłowy, ciąg JSONB pobrany z PostgreSQL. Chciałem go posortować według właściwości "order" w każdym obiekcie podrzędnym.

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);

Ponieważ liczba węzłów w obiekcie jest znana, najpierw tworzę tablicę o określonej długości:

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

Następnie wykonaj iterację obiektu, umieszczając nowo utworzone tymczasowe obiekty w pożądanych miejscach w tablicy bez faktycznego "sortowania".

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);

5
2017-12-04 18:36





Próbowałem tego i działa dobrze!

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

Indeks to pozycja, w której chcesz wstawić lub usunąć element. 0 tj. Drugie parametry określają liczbę elementów z indeksu do usunięcia item to nowe wpisy, które chcesz wprowadzić w tablicy. Może to być jeden lub więcej niż jeden.

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

2
2018-03-08 06:35



po prostu kopia wkleiła odpowiedź powyżej. to nie dodaje żadnej wartości do pytania. albo dodaj nową odpowiedź lub komentarz do istniejącej. spróbuj przekazać coś nowego. nie chcemy zepsuć tej społeczności - hannad rehman