JavaScriptでの配列要素の削除-削除とスプライス


1334

メソッドを使用するのではなく、配列要素で演算子を使用するdeleteことの違いは何ですか?Array.splice

例えば:

myArray = ['a', 'b', 'c', 'd'];

delete myArray[1];
//  or
myArray.splice (1, 1);

オブジェクトのように配列要素を削除できるのに、なぜスプライスメソッドを使用するのですか?


3
.spliceインループについては、この質問を見てください:javascriptの配列から削除してください
Rob W

6
@andynormancxはい、しかし、この回答は翌日に投稿され、非常に多くの票を獲得しました。
Camilo Martin

@andynormancx —完全に重複しているようには見えません。あなたがリンクした質問は、基本的になぜ配列から要素を削除する(したがって、それを疎にする)と長さが減らないのかと尋ねています。この質問は間の差異を求めているdeleteArray.prototype.splice
chharvey、2018

@chharveyは同意しました。より重要なのは、この質問が9年前にどのように投稿されたかです。ここに戻ってコメントしていると古く感じます
andynormancx '13 / 03/18

回答:


1693

deleteオブジェクトプロパティは削除されますが、配列のインデックスの再作成や長さの更新は行われません。これにより、未定義のように見えます。

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> delete myArray[0]
  true
> myArray[0]
  undefined

実際には値undefinedに設定されていないことに注意してください。プロパティは配列から削除され、定義されていないように見えます。Chrome開発ツールemptyは、アレイをログに記録するときに印刷することで、この区別を明確にします。

> myArray[0]
  undefined
> myArray
  [empty, "b", "c", "d"]

myArray.splice(start, deleteCount) 実際に要素を削除し、配列のインデックスを再作成して、その長さを変更します。

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> myArray.splice(0, 2)
  ["a", "b"]
> myArray
  ["c", "d"]

74
実際にdelete 、要素を削除しますが、配列のインデックスを再作成したり、その長さを更新したりしません(長さは常に最大のインデックス+1であるため、前者によってすでに暗示されています)。
Felix Kling

3
JSlintはdelete myArray[0]演算子を期待し、代わりに「削除」を見た」という構文は好きではありません使用することspliceをお勧めします。
瞳の

21
@Eye:実際、JSLintは前の行にセミコロンがないことについて不平を言っています。また、まったく異なることをしているため、どちらか一方を実際に推奨することはできません…
Ry-

3
「この場合の削除は、要素を未定義としてのみ設定します:」いいえ、それは明らかに間違っています。との間には根本的な違いがdelete myArray[0]ありmyArray[0] = undefinedます。前者の場合、プロパティは配列オブジェクトから完全に削除されます。2番目のケースでは、プロパティは値とともに残りますundefined
TJクラウダー2017

1
ちなみに、Chrome開発ツールは、実際に削除された(または初期化されていない)配列要素と、実際の値がである要素との違いを改善するempty代わりに、キーワードを表示しundefinedますundefined。これは私が言うように、としてのみ表示されることを意味emptyし、呼び出されたempty(存在しない)実際の値を参照しないことに注意してください。
chharvey

340

Array.remove()メソッド

jQueryの作成者であるJohn ResigArray.removeは、プロジェクトで常に使用する非常に便利なメソッドを作成しました。

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

そして、これがどのように使用されるかのいくつかの例です:

// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);

ジョンのウェブサイト


4
+1(Array.remove()の場合)。ただし、文字列引数が渡されるのは(たとえば、ほとんどのArrayメソッドとは異なり[1,2,3].slice('1'); // =[2,3])不愉快なので、次のように変更する方が安全ですvar rest = this.slice(parseInt(to || from) + 1 || this.length);
Richard Inglis

1
@ tomwrong、javascriptにスレッドがなく、関数が実行されthis.push.apply(this, rest)、返された値を返します
Billy

59
これはまったく質問に答えません。
Ry-

16
なぜsplice()を使用しないのですか?この関数の名前、パラメーター名、および結果は明確ではありません。私の推奨は、splice(index、length)を使用することです-(Andy Humeの回答を参照)
auco

3
上記の関数は説明どおりに機能しますが、配列をfor(var i in array)サイクルで反復するときに不要な副作用が発生します。私はそれを取り除き、代わりにスプライスを使用しました。
alexykot 2013

104

deleteは配列の要素からオブジェクトを削除するだけなので、配列の長さは変わりません。スプライスはオブジェクトを削除し、配列を短くします。

次のコードは、「a」、「b」、「undefined」、「d」を表示します

myArray = ['a', 'b', 'c', 'd']; delete myArray[2];

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

これは「a」、「b」、「d」を表示しますが

myArray = ['a', 'b', 'c', 'd']; myArray.splice(2,1);

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

11
1,1を使用した2番目の例のあいまいさを除いて素晴らしい例-最初の1はスプライスを開始する配列のインデックスを参照し、2番目の1は削除する要素の数です。したがって、元の配列から「c」を削除するには、次を使用しますmyArray.splice(2,1)
iancoleman

68

ある要素のすべての出現を配列から削除する方法を理解しようとしているときに、私はこの質問に遭遇しました。ここでの比較だsplicedelete、すべてを除去するため'c'items配列が。

var items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  items.splice(items.indexOf('c'), 1);
}

console.log(items); // ["a", "b", "d", "a", "b", "d"]

items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  delete items[items.indexOf('c')];
}

console.log(items); // ["a", "b", undefined, "d", "a", "b", undefined, "d"]


10

splice 数値インデックスで動作します。

一方 delete他の種類のインデックスに対して使用できます。

例:

delete myArray['text1'];

9
「他の種類のインデックス」と言うときは、もはや配列についてではなく、オブジェクトについてです。これは、OPが求めていることです。
Yi Jiang

2
@YiJiang:配列はオブジェクトです。Indizeはプロパティです。違いはありません。
ベルギ

9

また、スプライスは配列でのみ機能することにも言及する価値があります。(オブジェクトプロパティは、一貫した順序に従うことはできません。)

オブジェクトからキーと値のペアを削除するには、deleteが実際に必要なものです。

delete myObj.propName;     // , or:
delete myObj["propName"];  // Equivalent.

deleteは配列キーの順序を変更しないので、次のようにします。var arr = [1,2,3,4,5]; arr [3]を削除します。for(var i = 0; i <= arr.length; i ++)console.log(arr [i]); 予期しない結果を示します。
クリスチャンウィリアムズ

これは本当です。そのため、その場所に未定義の項目を残したくない場合を除き、配列のキーに削除を使用しないでください。最初にこのコメントを追加して、削除の正しい使用法のリファレンスを含めました。
jtrick 2016

しかし、なぜ削除すると予期しない結果がスローされますか?
Alex

9

対スプライスを削除

配列からアイテムを削除したとき

var arr = [1,2,3,4]; delete arr[2]; //result [1, 2, 3:, 4]
console.log(arr)

あなたがスプライスするとき

var arr = [1,2,3,4]; arr.splice(1,1); //result [1, 3, 4]
console.log(arr);

削除の場合、要素は削除されますが、インデックスは空のままです

一方、スプライス要素の場合は削除され、残りの要素インデックスはそれに応じて減少します


8

上記で何度も述べたように、使用splice()は完全に適合しているように見えます。Mozillaのドキュメント:

このsplice()メソッドは、既存の要素を削除したり、新しい要素を追加したりして、配列の内容を変更します。

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];

myFish.splice(2, 0, 'drum'); 
// myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"]

myFish.splice(2, 1); 
// myFish is ["angel", "clown", "mandarin", "sturgeon"]

構文

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

パラメーター

開始

配列の変更を開始するインデックス。配列の長さよりも大きい場合、実際の開始インデックスは配列の長さに設定されます。負の場合、最後から多くの要素を開始します。

deleteCount

削除する古い配列要素の数を示す整数。deleteCountが0の場合、要素は削除されません。この場合、少なくとも1つの新しい要素を指定する必要があります。deleteCountがstartから始まる配列に残っている要素の数より大きい場合、配列の最後までのすべての要素が削除されます。

deleteCountを省略すると、deleteCountは (arr.length - start).

item1、item2、...

開始インデックスから始まる、配列に追加する要素。要素を指定しない場合、splice()は、配列から要素のみが削除されます。

戻り値

削除された要素を含む配列。要素を1つだけ削除すると、1つの要素の配列が返されます。要素が削除されない場合、空の配列が返されます。

[...]


@downvoter:なぜ反対票か 説明するかどうか
serv-inc 2017

7

deleteは非現実的な状況のように動作し、アイテムを削除するだけですが、配列の長さは同じままです:

ノードターミナルからの例:

> var arr = ["a","b","c","d"];
> delete arr[2]
true
> arr
[ 'a', 'b', , 'd', 'e' ]

以下は、slice()を使用して配列の項目をインデックスで削除する関数です。最初の引数としてarrを取り、2番目の引数として削除するメンバーのインデックスを受け取ります。ご覧のように、実際には配列のメンバーを削除し、配列の長さを1減らします

function(arr,arrIndex){
    return arr.slice(0,arrIndex).concat(arr.slice(arrIndex + 1));
}

上記の関数は、インデックスまでのすべてのメンバーと、インデックスの後のすべてのメンバーを取得し、それらを連結して、結果を返します。

上記の関数をノードモジュールとして使用した例を次に示します。ターミナルが役立つことを確認してください。

> var arr = ["a","b","c","d"]
> arr
[ 'a', 'b', 'c', 'd' ]
> arr.length
4 
> var arrayRemoveIndex = require("./lib/array_remove_index");
> var newArray = arrayRemoveIndex(arr,arr.indexOf('c'))
> newArray
[ 'a', 'b', 'd' ] // c ya later
> newArray.length
3

indexOf( "c")は最初の出現を取得し、最初に見つかった "c"のみをスプライスして削除するため、これはdupeを含む1つの配列では機能しないことに注意してください。


6

大規模な配列を反復処理して要素を選択的に削除する場合、splice()は後続の要素のインデックスを毎回再作成する必要があるため、削除ごとにsplice()を呼び出すのはコストがかかります。配列はJavaScriptで関連付けられるため、個々の要素を削除してから、後で配列のインデックスを再作成する方が効率的です。

新しいアレイを構築することでそれを行うことができます。例えば

function reindexArray( array )
{
       var result = [];
        for( var key in array )
                result.push( array[key] );
        return result;
};

しかし、元の配列のキー値を変更することはできないと思います。これはより効率的です-新しい配列を作成する必要があるようです。

「未定義」のエントリは実際には存在せず、forループはそれらを返さないため、チェックする必要がないことに注意してください。それらを未定義として表示するのは、配列印刷のアーティファクトです。彼らは記憶に存在するようには見えません。

あなたがより速くなるslice()のようなものを使うことができればそれは素晴らしいですが、それは再インデックスしません。誰かがより良い方法を知っていますか?


実際には、おそらく次のようにその場所でそれを行うことができます。

reindexArray : function( array )
{
    var index = 0;                          // The index where the element should be
    for( var key in array )                 // Iterate the array
    {
        if( parseInt( key ) !== index )     // If the element is out of sequence
        {
            array[index] = array[key];      // Move it to the correct, earlier position in the array
            ++index;                        // Update the index
        }
    }

    array.splice( index );  // Remove any remaining elements (These will be duplicates of earlier items)
},

私は++ indexを信じています。「if」の外で発生する必要があります。編集
Mishal153 '29

6

あなたはこのようなものを使うことができます

var my_array = [1,2,3,4,5,6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';})); // [1,2,3,4,6]


これはslice、機能的なバックグラウンドを持っている場合よりも直感的です(ただし、おそらく効率が低下します)。
jethro

3

なぜフィルタリングしないのですか?私はそれがjsの配列を考える最も明確な方法だと思います。

myArray = myArray.filter(function(item){
    return item.anProperty != whoShouldBeDeleted
});

数百ではないにしても数百のレコードがあり、そのうち3つだけを削除すればよい配列についてはどうでしょうか。
Joel Hernandez

いい視点ね。このメソッドは、長さが200または300以下のスパース配列に使用し、パフォーマンスが非常に優れています。ただし、そのようなより大きな配列を管理する必要がある場合は、下線のようなライブラリーをお勧めします。
Asqan 2016年

1
しかし、それはよりもはるかに良く思わdeleteslice私には。
Juneyoungああ

3

違いは、delete演算子とsplice()メソッドが適用された後に各配列の長さを記録することで確認できます。例えば:

演算子を削除する

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];

console.log(trees); // ["redwood", "bay", "cedar", empty, "maple"]
console.log(trees.length); // 5

deleteオペレータは、配列から要素を削除するが、要素の「プレースホルダー」がまだ存在します。oak削除されましたが、それでもアレイのスペースが必要です。このため、配列の長さは5のままです。

splice()メソッド

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);

console.log(trees); // ["redwood", "bay", "cedar", "maple"]
console.log(trees.length); // 4

このsplice()メソッドは、ターゲット値「プレースホルダー」も完全に削除します。oakアレイで使用していたスペースと同様に削除されました。配列の長さが4になりました。


2
function remove_array_value(array, value) {
    var index = array.indexOf(value);
    if (index >= 0) {
        array.splice(index, 1);
        reindex_array(array);
    }
}
function reindex_array(array) {
   var result = [];
    for (var key in array) {
        result.push(array[key]);
    }
    return result;
}

例:

var example_arr = ['apple', 'banana', 'lemon'];   // length = 3
remove_array_value(example_arr, 'banana');

バナナが削除され、配列の長さ= 2


2

それらは異なる目的を持つ異なるものです。

spliceアレイから除去するエントリを削除するために使用される場合、配列特異的であり、そしてギャップを埋めるために移動する前のすべてのエントリを。(エントリを挿入するために使用することも、同時に両方を使用することもできます。)配列のspliceを変更しますlength(何もしない呼び出しではないと仮定します:)theArray.splice(x, 0)

deleteアレイ固有ではありません。オブジェクトで使用するために設計されています。使用するオブジェクトからプロパティ(キー/値のペア)を削除します。JavaScriptの標準(例:型指定されていない)配列は実際には配列ではないため、配列にのみ適用されます。*それらは、名前が「配列インデックス」であるような特定のプロパティを特別に処理するオブジェクトです(文字列名として定義されます "...その数値iは範囲内にあります+0 ≤ i < 2^32-1")およびlength。を使用deleteして配列エントリを削除する場合は、エントリを削除するだけです。ギャップを埋めるためにそれに続く他のエントリは移動しないため、配列は「スパース」になります(一部のエントリが完全に欠落しています)。には影響しませんlength

この質問に対する現在の回答のいくつかは、delete「を使用してエントリを設定する」と誤って述べていundefinedます。不正解です。エントリ(プロパティ)を完全に削除し、ギャップを残します。

いくつかのコードを使用して違いを説明しましょう:

console.log("Using `splice`:");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a.splice(0, 1);
console.log(a.length);            // 4
console.log(a[0]);                // "b"

console.log("Using `delete`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
delete a[0];
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // false
console.log(a.hasOwnProperty(0)); // false

console.log("Setting to `undefined`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a[0] = undefined;
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // true
console.log(a.hasOwnProperty(0)); // true


* (これは私の貧血の小さなブログの投稿です)


2

現在これを行うには2つの方法があります

  1. splice()の使用

    arrayObject.splice(index, 1);

  2. 削除を使用する

    delete arrayObject[index];

ただし、削除では配列の長さが更新されないため、配列オブジェクトにはスプライスを使用し、オブジェクト属性には削除を使用することを常にお勧めします。


1

OK、以下の配列があるとします。

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

最初に削除しましょう:

delete arr[1];

これが結果です:

[1, empty, 3, 4, 5];

空の!それを取得しましょう:

arr[1]; //undefined

つまり、値が削除されただけで現在は未定義であるため、長さは同じであり、trueを返します ...

配列をリセットして、今度はスプライスを使用してみましょう。

arr.splice(1, 1);

そしてこれが今回の結果です:

[1, 3, 4, 5];

配列の長さが変更され、現在arr[1]3であることがわかります...

また、これは削除されたアイテムを配列で返し[3]ます。この場合は...


1

他のものはすでにと適切に比較さdeleteれていますsplice

もう一つの興味深い比較であるdeleteundefined削除された配列の項目がちょうどに設定されているものよりも少ないメモリを使用していますundefined

たとえば、次のコードは終了しません:

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

このエラーが発生します:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

ご覧のとおり、undefined実際にはヒープメモリを消費します。

ただし、deleteary-itemも(単にに設定するのではなくundefined)場合、コードはゆっくり終了します。

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);

これらは極端な例ですが、deleteどこにも言及されている人を見たことがありません。


1

あなたが小さな配列を持っているなら、あなたは使うことができますfilter

myArray = ['a', 'b', 'c', 'd'];
myArray = myArray.filter(x => x !== 'b');

0

最も簡単な方法はおそらく

var myArray = ['a', 'b', 'c', 'd'];
delete myArray[1]; // ['a', undefined, 'c', 'd']. Then use lodash compact method to remove false, null, 0, "", undefined and NaN
myArray = _.compact(myArray); ['a', 'c', 'd'];

お役に立てれば。リファレンス:https : //lodash.com/docs#compact


1
誰かがこれについて不思議に思っcompactたら... lodashは必要ありません。試してみるmyArray.filter(function(n){return n;})
dat

0

Lodashを使用したい人のために使用することができます: myArray = _.without(myArray, itemToRemove)

または私がAngular2で使用するように

import { without } from 'lodash';
...
myArray = without(myArray, itemToRemove);
...

0

delete:deleteはオブジェクトプロパティを削除しますが、配列のインデックスを再作成したり、その長さを更新したりしません。これにより、未定義のように見えます。

splice:実際に要素を削除し、配列のインデックスを再作成して、その長さを変更します。

最後から要素を削除

arrName.pop();

最初から要素を削除

arrName.shift();

真ん中から削除

arrName.splice(starting index,number of element you wnt to delete);

Ex: arrName.splice(1,1);

最後から1つの要素を削除

arrName.splice(-1);

配列のインデックス番号を使用して削除

 delete arrName[1];

0

削除したい要素が途中にある場合(たとえば、インデックスが1である「c」を削除したい場合)、次のように使用できます。

var arr = ['a','b','c'];
var indexToDelete = 1;
var newArray = arr.slice(0,indexToDelete).combine(arr.slice(indexToDelete+1, arr.length))

0

IndexOf参照タイプも受け入れます。次のシナリオを想定します。

var arr = [{item: 1}, {item: 2}, {item: 3}];
var found = find(2, 3); //pseudo code: will return [{item: 2}, {item:3}]
var l = found.length;

while(l--) {
   var index = arr.indexOf(found[l])
      arr.splice(index, 1);
   }
   
console.log(arr.length); //1

異なる:

var item2 = findUnique(2); //will return {item: 2}
var l = arr.length;
var found = false;
  while(!found && l--) {
  found = arr[l] === item2;
}

console.log(l, arr[l]);// l is index, arr[l] is the item you look for

-1
function deleteFromArray(array, indexToDelete){
  var remain = new Array();
  for(var i in array){
    if(array[i] == indexToDelete){
      continue;
    }
    remain.push(array[i]);
  }
  return remain;
}

myArray = ['a', 'b', 'c', 'd'];
deleteFromArray(myArray , 0);

//結果:myArray = ['b'、 'c'、 'd'];


@ChrisDennisなんで?(皮肉や悪意は意図されていません。これは誠実な質問です)
Chris Bier

この答えはOPの質問に対処していないという事実のほかに
クリスBIER
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.