web-dev-qa-db-ja.com

JavaScriptで配列要素を削除する - delete vs splice

Array.spliceメソッド の使用とは対照的に、 delete演算子 の使用と配列要素での違いは何ですか? 

例えば:

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

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

オブジェクトの場合のように配列要素を削除できれば、なぜspliceメソッドさえあるのでしょうか。

1245
lYriCAlsSH

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

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

実際には値undefinedに設定されているのではなく、プロパティが配列から削除され、 出現 未定義になっています。 Chrome devツールは、配列をログに記録するときに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"]
1622
Andy Hume

Array.remove()メソッド

John Resig 、jQueryの作成者は非常に便利なArray.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);

ジョンのウェブサイト

330
Mohsen

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]);
}
99
andynormancx

配列から要素の出現をすべて削除する方法を理解しようとしているときに、私はこの質問に出くわしました。 splice配列からすべての'c'を削除するためのdeleteitemsの比較 .

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"]
​
63
Troy Harvey

From Core JavaScript 1.5リファレンス>演算子>特殊演算子> delete演算子

配列要素を削除しても、配列の長さは影響を受けません。 の例では、[3]を削除しても[4]は[4]、[3]は未定義です。このは、配列の最後の要素を削除した場合でも同じです(delete a [a.length-1])。

14
f3lix

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

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

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

spliceは数値インデックスを処理します。

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

例:

delete myArray['text1'];
9
Gopal

何度も述べたように、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つの要素の配列が返されます。要素が削除されていない場合は、空の配列が返されます。

[...]

8
serv-inc

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"のみをスプライスアウトして削除するため、これは重複がある1つの配列では機能しません。

7
med116

Vs spliceを削除します

配列から項目を削除したとき

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

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

splice要素の場合は削除され、それに応じてrest要素のindexは減少します

7
ashish yadav

大きな配列を繰り返して要素を選択的に削除したい場合、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)
},
6
Mike T

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

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]

5
Zeeshan Saleem

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

spliceは配列固有であり、削除に使用すると、配列からエントリを削除しギャップを埋めるために前のエントリをすべて上に移動します。 (エントリの挿入、またはその両方に同時に使用することもできます。)spliceは、配列のlengthを変更します(no-op呼び出しではない場合:theArray.splice(x, 0)) 。

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

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

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

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
T.J. Crowder
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
Terry Lin

現在これをする2つの方法があります 

  1. splice()を使う

    arrayObject.splice(index, 1);

  2. 削除を使用

    delete arrayObject[index];

ただし、deleteは配列の長さを更新しないため、配列オブジェクトにはspliceを、オブジェクト属性にはdeleteを使用することをお勧めします。 

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

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

違いは、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になりました。

1
underthecode

OK、この配列が下にあると想像してください。

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

まず削除しましょう。

delete arr[1];

これが結果です。

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

空の! そしてそれを手に入れましょう:

arr[1]; //undefined

つまり、削除された値だけを意味し、 undefined nowで、長さは同じです。また、 true ...も返されます。

今度は配列をリセットして、今度はspliceで行いましょう。

arr.splice(1, 1);

これが今回の結果です。

[1, 3, 4, 5];

ご覧のとおり、配列の長さが変わり、arr[1] 3 now ...

また、これは削除された項目をこの場合[3]である配列で返します...

1
Alireza

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
Srikrushna Pal

削除したい要素が真ん中にある場合(インデックスが1の 'c'を削除したいとします)、

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

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
0
roland

Lodash を使いたい人のために: myArray = _.without(myArray, itemToRemove)

またはAngular 2で使用しているように

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

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

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

0
Prashanth