配列から特定のアイテムを削除するにはどうすればよいですか?


8297

数値の配列があり、それに.push()メソッドを使用して要素を追加しています。

配列から特定の要素を削除する簡単な方法はありますか?

私は次のようなものと同等のものを探しています:

array.remove(number);

コア JavaScript を使用する必要があります。フレームワークは許可されていません。

回答:


11891

index使用して削除する配列要素のを検索し、indexOf次にそのインデックスを削除しますsplice

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

const array = [2, 5, 9];

console.log(array);

const index = array.indexOf(5);
if (index > -1) {
  array.splice(index, 1);
}

// array = [2, 9]
console.log(array); 

の2番目のパラメータspliceは、削除する要素の数です。ご了承くださいsplice配列適切に変更し、削除された要素を含む新しい配列を返す。


完全性のために、ここに関数があります。最初の関数は単一のオカレンスのみを削除します(つまり、5fromの最初の一致を[2,5,9,1,5,8,5]削除します)、2番目の関数はすべてのオカレンスを削除します。

function removeItemOnce(arr, value) { 
    var index = arr.indexOf(value);
    if (index > -1) {
        arr.splice(index, 1);
    }
    return arr;
}

function removeItemAll(arr, value) {
    var i = 0;
    while (i < arr.length) {
        if(arr[i] === value) {
            arr.splice(i, 1);
        } else {
            ++i;
        }
    }
    return arr;
}

15
@ピーター、はいあなたは正しいかもしれません。この記事では、より説明し、互換性のないブラウザのための回避策があります。developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
トムWadley

33
@AlexandreWiechersVazもちろん、それは順序を維持します。もしそうでなければ、それは絶対に価値がありません
TheZ

15
コードを含めることにより、IEブラウザーサポートの問題を克服できます。 ここにます

15
@AdrianP。array.indexOf(testValue)空の配列では-1になり、それをテストする場合はスプライスはありません。それ以来、答えが変わったのかもしれません。
UpTheCreek 2015年

13
IE 7、IE8、IE9、IE10はMicrosoft自体ではサポートされていません。なぜWeb開発者がこれらの古いブラウザーをサポートする必要があるのですか?ブラウザのアップグレードに関する通知を表示するだけです!support.microsoft.com/en-us/lifecycle/...
ルーカス・Liesis

1268

あなたがどのようarray.remove(int)に行動することを期待しているのか、私にはわかりません。あなたが望むかもしれないと私が考えることができる3つの可能性があります。

インデックスの配列の要素を削除するにはi

array.splice(i, 1);

number配列から値を持つすべての要素を削除する場合:

for(var i = array.length - 1; i >= 0; i--) {
    if(array[i] === number) {
        array.splice(i, 1);
    }
}

インデックスiの要素をもう存在させたくないが、他の要素のインデックスを変更したくない場合:

delete array[i];

335
delete配列から要素を削除する正しい方法ではありません!
Felix Kling 2013年

71
@FelixKling場合によっては、その位置に要素がarray.hasOwnProperty(i)戻るように戻りたい場合に機能します。しかし、それがやりたいことはあまり一般的ではないことを認めます。falseundefined
Peter Olson 2013年

88
delete配列の長さを更新せず、要素を実際に消去せず、特別な値に置き換えるだけですundefined
diosney 2013

34
@diosneyあなたがそれが本当に要素を消去しないと言うとき、私はあなたが何を意味するのかわかりません。さらに、そのインデックスの値を単に次のものに置き換えるだけではありませんundefined。それは、インデックスと値の両方を配列から削除します。つまり、の後delete array[0]"0" in arrayfalseを返します。
Peter Olson

17
@GrantGryczan申し訳ありませんが、私は同意しません。これを削除する必要はないと思います。上記のテキストはそれが何をするのかを明確に説明しており、それが何deleteをするのかを知らない人々が期待通りに機能しない理由を理解するのに役立ちます。
Peter Olson

1205

2016年10月に編集

  • シンプルで直感的で明確なことをしてください(Occamのかみそり
  • 不変ですか(元の配列は変更されません)
  • ブラウザがサポートしていない場合は、標準のJavaScript関数を使用してください- ポリフィルを使用してください

このコード例では、「array.filter(...)」関数を使用して、不要なアイテムを配列から削除しています。この関数は元の配列を変更せず、新しい配列を作成します。ご使用のブラウザーがこの機能をサポートしていない場合(例えば、バージョン9より前のInternet Explorer、またはバージョン1.5より前のFirefox)、Mozillaのフィルターポリフィルの使用を検討してください。

アイテムの削除(ECMA-262 Edition 5コード、別名oldstyle JavaScript)

var value = 3

var arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(function(item) {
    return item !== value
})

console.log(arr)
// [ 1, 2, 4, 5 ]

アイテムの削除(ECMAScript 6コード)

let value = 3

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => item !== value)

console.log(arr)
// [ 1, 2, 4, 5 ]

重要 ECMAScript 6 "()=> {}"矢印関数構文は、Internet Explorer、45より前のバージョンのChrome、22より前のバージョンのFirefox、および10より前のバージョンのSafariではサポートされていません。古いブラウザーでECMAScript 6構文を使用するには、BabelJSを使用できます。


複数のアイテムの削除(ECMAScript 7コード)

この方法の追加の利点は、複数のアイテムを削除できることです

let forDeletion = [2, 3, 5]

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!

console.log(arr)
// [ 1, 4 ]

重要「array.includes(...)」関数はInternet Explorer、47バージョンより前のChrome、43バージョンより前のFirefox、9バージョンより前のSafari、および14バージョンより前のEdgeではまったくサポートされていないため、Mozillaからのポリフィルます。

複数のアイテムの削除(将来的には)

「This-Binding Syntax」の提案が受け入れられた場合、これを行うことができます。

// array-lib.js

export function remove(...forDeletion) {
    return this.filter(item => !forDeletion.includes(item))
}

// main.js

import { remove } from './array-lib.js'

let arr = [1, 2, 3, 4, 5, 3]

// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)

console.log(arr)
// [ 1, 4 ]

BabelJSで試してみてください:)

参照


6
ただし、元の配列(不変ではない)から要素を削除したい場合もあります。たとえば、Angular 2 * ngForディレクティブで使用されている配列
Ravinder Payal

43
一致が1回だけ発生することを想定しておらず、不変性が望ましいため、一般に認められているソリューションよりも優れています
グレッグ

13
filterしかし、大きな配列の場合ははるかに遅くなる必要がありますか?
ネイサン

3
例で同じ変数の代入を使用した場合、不変性のポイントは何ですか?:)
2017

12
これは素晴らしい答えです。スプライスは、フィルタリングではなく突然変異を行うための特殊な機能です。filterパフォーマンスが低下する可能性がありますが、コードはより安全で優れています。また、あなたはラムダで二番目の引数を指定して、インデックスによってフィルタリングすることができます:arr.filter((x,i)=>i!==2)
マシュー・

449

空のスポットを維持するかどうかによって異なります。

空のスロットが必要な場合は、削除しても問題ありません。

delete array[index];

そうでない場合は、spliceメソッドを使用する必要があります。

array.splice(index, 1);

そして、その項目の値が必要な場合は、返された配列の要素を格納するだけです。

var value = array.splice(index, 1)[0];

ある順序で実行したい場合array.pop()は、最後の1つまたはarray.shift()最初の1 つに使用できます(両方ともアイテムの値も返します)。

また、アイテムのインデックスがわからない場合は、を使用array.indexOf(item)して取得できます(aでif()1つのアイテムを取得するか、aでwhile()すべてを取得します)。array.indexOf(item)インデックスを返すか、見つからない場合は-1を返します。 


25
delete配列から要素を削除する正しい方法ではありません!!
プロゴ2014

16
「スロットを空にする」場合は、を使用しますarray[index] = undefined;。使用deleteすると最適化が破壊されます。
ベルギ2014

4
@Jakubは非常に良いコメントです。私が多くの時間を失い、私のアプリケーションコードがどういうわけか壊れていると思ったので...
Pascal

indexOfから何が得られるかを説明した最後の段落は本当に役に立ちました
A. D'Alfonso

277

友人がInternet Explorer 8で問題を抱えていて、彼が何をしたかを見せてくれました。私はそれが間違っていると彼に言った、そして彼はここで答えを得たと私に言った。現在の上位の回答は、すべてのブラウザー(Internet Explorer 8など)では機能せず、アイテムの最初の出現のみを削除します。

配列からすべてのインスタンスを削除する

function remove(arr, item) {
    for (var i = arr.length; i--;) {
        if (arr[i] === item) {
            arr.splice(i, 1);
        }
    }
}

(項目が削除されるとインデックスと長さが変わるため)配列を逆方向にループし、見つかった場合はその項目を削除します。すべてのブラウザで動作します。


11
@sroesループは最大インデックスで開始するi = arr.length -1i--、最大インデックスと同じになるため、そうなってはなりません。arr.lengthはの初期値ですii--が(偽の値)に等しくなり、ループが停止するまで、常に真実(および各ループ操作で1ずつ減少0)になります。
gmajivu 2014年

1
2番目の機能はかなり非効率的です。すべての反復で、「indexOf」は配列の先頭から検索を開始します。
ujeenator 2015

3
@AmberdeBlack、itemが2回以上出現するコレクションでは、代わりにfilterメソッドを呼び出してarr.filter(function (el) { return el !== item })、配列を複数回変更する必要を回避することをお勧めします。これはわずかに多くのメモリを消費しますが、実行する必要がある作業が少ないため、はるかに効率的に動作します。
ユージーンクズメンコ2015年

1
@AlJey、それはIE9 +からのみ利用可能です。それが機能しない可能性はまだあります。
ujeenator 2015年

1
いくつかのアイテムを削除する必要があるが、特定の順序ではないため、この回答が役に立ちました。forループの後方への進行は、配列からの項目の削除を完全に処理します。
mintedsky

172

2つの主要なアプローチがあります。

  1. splice()anArray.splice(index, 1);

  2. 削除delete anArray[index];

配列の削除を使用するときは注意してください。オブジェクトの属性の削除には適していますが、配列にはあまり適していません。使う方がいいsplice配列をお勧めします。

delete配列に使用すると、に対して誤った結果が得られる可能性があることに注意してくださいanArray.length。言い換えると、delete要素は削除されますが、長さプロパティの値は更新されません。

また、削除を使用した後、インデックス1、3、4、8、9、および11と長さを持つことになる可能性があります。その場合、forインデックスがシーケンシャルではなくなるため、すべてのインデックス付きループがクラッシュします。

delete何らかの理由で強制的に使用for eachする場合は、配列をループする必要があるときにループを使用する必要があります。実際のところ、for可能であれば、常にインデックス付きループの使用は避けてください。そうすれば、コードはより堅牢になり、インデックスに関する問題が発生しにくくなります。


144
Array.prototype.remByVal = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === val) {
            this.splice(i, 1);
            i--;
        }
    }
    return this;
}
//Call like
[1, 2, 3, 4].remByVal(3);

Array.prototype.remByVal = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === val) {
            this.splice(i, 1);
            i--;
        }
    }
    return this;
}

var rooms = ['hello', 'something']

rooms = rooms.remByVal('hello')

console.log(rooms)


14
私はこのアプローチの大ファンではありません。異なるライブラリまたはフレームワークを使用することになる場合、それらは互いに競合することになります。
チャーリーキリアン2011

10
悪い考え、この投稿を参照:stackoverflow.com/questions/948358/array-prototype-problem
MMeah

10
あなたがやっている場合はfor in、アレイ上に、あなたはすでに問題を抱えています。
Zirak、2014年

2
あなたがしなければfor inアレイ上で、あなたはすでに大きな問題を抱えています。
Rainb

Object.defineProperty stackoverflow.com/a/35518127/3779853を使用してください。
phil294 2018

105

indexOfまたはを使用する必要はありませんsplice。ただし、要素を1つだけ削除したい場合は、パフォーマンスが向上します。

検索して移動(移動):

function move(arr, val) {
  var j = 0;
  for (var i = 0, l = arr.length; i < l; i++) {
    if (arr[i] !== val) {
      arr[j++] = arr[i];
    }
  }
  arr.length = j;
}

indexOfおよびsplice(indexof)の使用:

function indexof(arr, val) {
  var i;
  while ((i = arr.indexOf(val)) != -1) {
    arr.splice(i, 1);
  }
}

のみ使用splice(スプライス):

function splice(arr, val) {
  for (var i = arr.length; i--;) {
    if (arr[i] === val) {
      arr.splice(i, 1);
    }
  }
}

1000個の要素を持つ配列のnodejsでの実行時間(平均10000回を超える実行):

indexofmoveよりも約10倍遅くなります。indexOfin spliceへの呼び出しを削除することで改善されたとしても、moveよりもはるかにパフォーマンスが悪い。

Remove all occurrences:
    move 0.0048 ms
    indexof 0.0463 ms
    splice 0.0359 ms

Remove first occurrence:
    move_one 0.0041 ms
    indexof_one 0.0021 ms

5
ここに示す 'move'メソッドはすべてのブラウザで機能するようであり、追加の配列の作成も回避しています。ここでの他のほとんどのソリューションには、これらの問題の一方または両方があります。これは「きれい」に見えなくても、これはもっと多くの投票に値すると思います。
sockmonk 2015

73

これは、値の代わりに述語を提供します。

注:指定された配列を更新し、影響を受ける行を返します。

使用法

var removed = helper.removeOne(arr, row => row.id === 5 );

var removed = helper.remove(arr, row => row.name.startsWith('BMW'));

定義

var helper = {

    // Remove and return the first occurrence

    removeOne: function(array, predicate) {
        for (var i = 0; i < array.length; i++) {
            if (predicate(array[i])) {
                return array.splice(i, 1);
            }
        }
    },

    // Remove and return all occurrences

    remove: function(array, predicate) {
        var removed = [];

        for (var i = 0; i < array.length;) {

            if (predicate(array[i])) {
                removed.push(array.splice(i, 1));
                continue;
            }
            i++;
        }
        return removed;
    }
};

-1チェック(i> -1)が必要かどうかはわかりません。また、これらの関数は削除よりもフィルターのように機能すると思います。row.id === 5を渡すと、結果はid 5のみの配列になるため、削除の逆を行います。ES2015では見栄えがします。var result = ArrayHelper.remove(myArray、row => row.id === 5);
何をクールになる

@WhatWouldBeCoolこの関数は元の配列を変更し、結果を新しい配列にコピーする代わりに削除されたアイテムを返します
amd

68

あなたはfilterメソッドでそれを簡単に行うことができます:

function remove(arrOriginal, elementToRemove){
    return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log(remove([1, 2, 1, 0, 3, 1, 4], 1));

これは、配列からすべての要素を削除しても、の組み合わせよりも速く動作しますsliceindexOf


3
これが速いという情報源はありますか?
user3711421 2017

2
素晴らしい解決策。しかし、指摘したように、ハゲを作ることが重要ですが、1のすべての出現を削除するため、sliceおよびindexOfと同じ結果は生成されません
user3711421

1
@ user3711421これは、sliceとindexOfが「特定の要素を削除する」ために望んでいることを実行しないためです。それは一度だけ要素を削除します、これはあなたがそれらをいくつ持っていても特定の要素を削除します
Salvador Dali

66

John Resig は良い実装を投稿しました

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

グローバルオブジェクトを拡張したくない場合は、代わりに次のようなことができます:

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

しかし、これを投稿する主な理由は、そのページのコメント(2007年12月14日)で提案されている代替実装に対してユーザーに警告するためです。

Array.prototype.remove = function(from, to){
  this.splice(from, (to=[0,from||1,++to-from][arguments.length])<0?this.length+to:to);
  return this.length;
};

最初はうまく機能しているように見えますが、配列内の最後から2番目の要素を削除しようとすると失敗することがわかりました。たとえば、10要素の配列があり、これを使用して9番目の要素を削除しようとすると、次のようになります。

myArray.remove(8);

結局、8要素の配列になります。理由はわかりませんが、ジョンの元の実装にはこの問題がないことを確認しました。


ただ、使用するのは良いアイデアですなぜハードな方法によって学習Object.prototype.hasOwnProperty¬¬常に
ダヴィFiamenghi

64

Underscore.jsは、複数のブラウザーの問題を解決するために使用できます。存在する場合は、組み込みのブラウザメソッドを使用します。古いバージョンのInternet Explorerの場合のように存在しない場合は、独自のカスタムメソッドを使用します。

配列から要素を削除する簡単な例(ウェブサイトから):

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]

エレガントで簡潔ですが、OPはコアJSのみを明確に言及しています
EigenFool

64

ES6を使用できます。たとえば、この場合に値「3」を削除するには、次のようにします。

var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
console.log(newArray);

出力:

["1", "2", "4", "5", "6"]

4
この答えは、元の配列を直接変更するのではなく、元の配列のコピーを作成するので、すばらしいです。
Claudio Holanda 2017年

注:Array.prototype.filterはECMAScript 5.1(IE8なし)です。より具体的なソリューション:stackoverflow.com/a/54390552/8958729
Chang

54

削除された位置が削除された新しい配列が必要な場合は、いつでも特定の要素を削除して、配列をフィルターで除外できます。filterメソッドを実装していないブラウザーの場合は、配列オブジェクトの拡張が必要になる可能性がありますが、長期的には、これを行うだけなので簡単です。

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]です。


45

このコードを確認してください。すべての主要なブラウザで動作します。

remove_item = function (arr, value) {
    var b = '';
    for (b in arr) {
        if (arr[b] === value) {
            arr.splice(b, 1);
            break;
        }
    }
    return arr;
}

この関数を呼び出す

remove_item(array,value);

4
@RolandIllig -loopの使用と、for inループから直接結果を返すことによってスクリプトがより早く停止する可能性があることを除いて。賛成票は妥当です;)
yckart 2014

1
これは、小さなアレイに最適なアプローチです。すべてのブラウザーで機能し、最小限の直感的なコードを使用し、余分な複雑なフレームワーク、シム、ポリフィルはありません。
Beejor

またfor( i = 0; i < arr.length; i++ )、ブラウザーがアイテムを(どのように)格納するかを決定する順序に対して正確なインデックスを保持するため、より良いアプローチとなるyckartのコメントを繰り返しfor inます。これにより、必要に応じて値の配列インデックスを取得することもできます。
Beejor

41

lodash _.pull(変異配列)、_。pullAt(変異配列)または_.without(変異配列ではない)を使用できます。

var array1 = ['a', 'b', 'c', 'd']
_.pull(array1, 'c')
console.log(array1) // ['a', 'b', 'd']

var array2 = ['e', 'f', 'g', 'h']
_.pullAt(array2, 0)
console.log(array2) // ['f', 'g', 'h']

var array3 = ['i', 'j', 'k', 'l']
var newArray = _.without(array3, 'i') // ['j', 'k', 'l']
console.log(array3) // ['i', 'j', 'k', 'l']

2
OPが要求したとおり、それはコアJSではありません。
some-non-descriptor-user

12
@ some-non-descript-userそのとおりです。しかし、私のような多くのユーザーは、OPだけでなく一般的な答えを求めてここに来ます。
チュンヤン

@ChunYangあなたは絶対に正しいです。私はすでにlodashを使用していますが、時間を節約するためにそれを使用しないでください。
int-i

38

ES6&変異なし:(2016年10月)

const removeByIndex = (list, index) =>
      [
        ...list.slice(0, index),
        ...list.slice(index + 1)
      ];
         
output = removeByIndex([33,22,11,44],1) //=> [33,11,44]
      
console.log(output)


なぜそれを使用しないのfilterですか?array.filter((_, index) => index !== removedIndex);
user4642212

@ user4642212あなたは正しいです!また、私はGolangスタイルのアンダースコアが好きでした
Abdennour TOUMI

36

配列から特定の要素/文字列を削除することはワンライナーで行うことができます:

theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);

どこ:

theArray:特定のものを削除する配列

stringToRemoveFromArray:削除する文字列。1は削除する要素の量です。

:「stringToRemoveFromArray」が配列内にない場合、これは配列の最後の要素を削除します。

要素を削除する前に、まず要素が配列に存在するかどうかを確認することをお勧めします。

if (theArray.indexOf("stringToRemoveFromArray") >= 0){
   theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
}

クライアントのコンピューターで新しいEcmascriptバージョンにアクセスできる場合(警告、古いステーションでは機能しない可能性があります):

var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');

ここで、「3」は配列から削除する値です。その後、配列は次のようになります。['1','2','4','5','6']


これは、ラジオボタンの切り替えに基づいて配列を更新しようとしたときにうまくいった答えです。
jdavid05

4
"stringToRemoveFromArray"が配列内にない場合は、配列の最後の要素が削除されることに注意してください。
Fusion

35

JavaScriptを使用して配列から項目削除するいくつかの方法を次に示します

説明されているすべてのメソッドは元の配列を変更しません、代わりに新しいを作成します。

アイテムのインデックスを知っている場合

配列があり、位置のアイテムを削除したいとしますi

1つの方法は使用することslice()です:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i).concat(items.slice(i+1, items.length))

console.log(filteredItems)

slice()受け取ったインデックスで新しい配列を作成します。最初から削除するインデックスまでの新しい配列を作成し、削除した配列に続く最初の位置から配列の最後まで別の配列を連結します。

価値を知っているなら

この場合、1つの適切なオプションはを使用することですfilter()。これは、より宣言的なアプローチを提供します。

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)

console.log(filteredItems)

ES6の矢印関数を使用します。従来の関数を使用して、古いブラウザーをサポートできます。

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
  return item !== valueToRemove
})

console.log(filteredItems)

または、Babelを使用してES6コードをES5にトランスパイルして、古いブラウザーでよりわかりやすくし、コードに最新のJavaScriptを記述できます。

複数のアイテムを削除する

単一のアイテムではなく、多くのアイテムを削除したい場合はどうなりますか?

最も簡単な解決策を見つけましょう。

インデックス別

関数を作成して、アイテムを順番に削除するだけです。

const items = ['a', 'b', 'c', 'd', 'e', 'f']

const removeItem = (items, i) =>
  items.slice(0, i-1).concat(items.slice(i, items.length))

let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]

console.log(filteredItems)

値で

コールバック関数内の包含を検索できます。

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]

console.log(filteredItems)

元の配列を変更しないでください

splice()(と混同しないでくださいslice())は元の配列を変更するため、回避する必要があります。

(元々はhttps://flaviocopes.com/how-to-remove-item-from-array/に投稿されています


34

OK、例えばあなたは以下の配列を持っています:

var num = [1, 2, 3, 4, 5];

そして、番号4を削除します。以下のコードを使用するだけです。

num.splice(num.indexOf(4), 1); // num will be [1, 2, 3, 5];

この関数を再利用する場合は、次のようにネイティブ配列関数にアタッチされる再利用可能な関数を記述します。

Array.prototype.remove = Array.prototype.remove || function(x) {
  const i = this.indexOf(x);
  if(i===-1)
      return;
  this.splice(i, 1); // num.remove(5) === [1, 2, 3];
}

しかし、配列にいくつかの[5]を含む以下の配列がある場合はどうでしょうか?

var num = [5, 6, 5, 4, 5, 1, 5];

すべてをチェックするためのループが必要ですが、組み込みのJavaScript関数を使用する方が簡単で効率的な方法なので、代わりに以下のようなフィルターを使用する関数を記述します。

const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) // Return [1, 2, 3, 4, 6]

また、LodashやUnderscoreなど、これを行うのに役立つサードパーティのライブラリもあります。詳細については、lodash _.pull、_。pullAt、または_.withoutを参照してください。


小さなタイプミスがあります。正してください。this.splice(num.indexOf(x), 1);=>this.splice(this.indexOf(x), 1);
TheGwa 2017年

JavaScriptの組み込み関数(Array.prototypeに関数をアタッチ)を拡張しないでください。これは悪い習慣と広く見なされています。
aikeru 2017年

それは世界で行うのが最善ではないことに同意しますが、この場合、それを関数に渡す方法を教えてください。
Alireza

インデックスを確認してください。index = -1の場合、splice(-1,1)は最後の要素を削除します
Richard Chan

29

私はJavaScriptにかなり慣れていないため、この機能が必要でした。私はこれを書いただけです:

function removeFromArray(array, item, index) {
  while((index = array.indexOf(item)) > -1) {
    array.splice(index, 1);
  }
}

次に、それを使用したい場合:

//Set-up some dummy data
var dummyObj = {name:"meow"};
var dummyArray = [dummyObj, "item1", "item1", "item2"];

//Remove the dummy data
removeFromArray(dummyArray, dummyObj);
removeFromArray(dummyArray, "item2");

出力-予想どおり。["item1"、 "item1"]

あなたは私とは異なるニーズがあるかもしれないので、それらに合うように簡単に変更することができます。これが誰かの役に立つことを願っています。


1
配列が本当に長く、その中に要素のインスタンスがいくつかある場合、これはひどい動作になります。配列のindexOfメソッドは毎回最初から開始されるため、コストはO(n ^ 2)になります。
ザグ

@Zag:それは名前を持っています:Shlemiel the Painter's Algorithm
Peter Mortensen

27

配列に複雑なオブジェクトがある場合、フィルターを使用できますか?$ .inArrayまたはarray.spliceが使いにくい状況で。特にオブジェクトが配列内でおそらく浅い場合。

たとえば、Idフィールドを持つオブジェクトがあり、そのオブジェクトを配列から削除したい場合は、次のようにします。

this.array = this.array.filter(function(element, i) {
    return element.id !== idToRemove;
});

これが私のやり方です。アロー関数を使用すると、ワンライナーにすることができます。パフォーマンスに興味があります。これ配列を置き換えることにも何の価値もありません。古い配列への参照を含むコードは、変更を認識しません。
joeytwiddle

27

ECMAScript 6に基づいて回答したいと思います。次のような配列があるとします。

let arr = [1,2,3,4];

のような特別なインデックスで削除したい場合は2、以下のコードを記述してください:

arr.splice(2, 1); //=> arr became [1,2,4]

ただし、などの特別なアイテムを削除したい3が、そのインデックスがわからない場合は、以下のようにします。

arr = arr.filter(e => e !== 3); //=> arr became [1,2,4]

ヒント:空の配列を取得しない限り、フィルターコールバックには矢印関数を使用してください。


25

更新:この方法は、ECMAScript 2015(旧称ES6)を使用できない場合にのみお勧めします。あなたがそれを使うことができるなら、ここでの他の答えはもっとすっきりした実装を提供します。


この要点は問題を解決し、1(または指定した値)だけでなく、引数のすべての出現を削除します。

Array.prototype.destroy = function(obj){
    // Return null if no objects were found and removed
    var destroyed = null;

    for(var i = 0; i < this.length; i++){

        // Use while-loop to find adjacent equal objects
        while(this[i] === obj){

            // Remove this[i] and store it within destroyed
            destroyed = this.splice(i, 1)[0];
        }
    }

    return destroyed;
}

使用法:

var x = [1, 2, 3, 3, true, false, undefined, false];

x.destroy(3);         // => 3
x.destroy(false);     // => false
x;                    // => [1, 2, true, undefined]

x.destroy(true);      // => true
x.destroy(undefined); // => undefined
x;                    // => [1, 2]

x.destroy(3);         // => null
x;                    // => [1, 2]

25

パフォーマンス

今日(2019-12-09)選択したソリューションのmacOS v10.13.6(High Sierra)でパフォーマンステストを実施します。見せますdelete(A)いますが、配列に空のスペースが残っているため、他の方法と比較して使用していません。

結論

  • 最速の解決策はarray.splice(C)です(2回目の小さなアレイのSafariを除く)
  • 大きな配列の場合、array.slice+splice(H)はFirefoxとSafariの最速の不変ソリューションです。Array.from(B)Chromeで最速
  • 可変ソリューションは通常、不変ソリューションより1.5倍から6倍高速です。
  • Safariの小さなテーブルの場合、驚くべきことに、可変ソリューション(C)は不変ソリューション(G)よりも遅い

細部

テストでは、さまざまな方法で配列から中央の要素を削除します。A、Cのソリューションは、インプレースです。B、D、E、F、G、Hソリューションは不変です。

10要素の配列の結果

ここに画像の説明を入力してください

Chromeでは、array.splice(C)が最速のインプレースソリューションです。array.filter(D)は、最速不変溶液です。最も遅いのはarray.slice(F)です。ここでマシンのテストを実行できます

1.000.000要素の配列の結果

ここに画像の説明を入力してください

Chromeでは、array.splice(C)が最速のインプレースソリューションです(delete(C)も同様に高速ですが、配列に空のスロットが残っています(したがって、「完全な削除」は実行されません))。array.slice-splice(H)は、最速の不変のソリューションです。最も遅いのはarray.filter(DおよびE)です。ここでマシンのテストを実行できます

ブラウザーの比較:Chrome v78.0.0、Safari v13.0.4、Firefox v71.0.0

ここに画像の説明を入力してください


24

配列を変更しないでください。これは関数型プログラミングパターンに反するためです。ECMAScript 6メソッドを使用して、データを変更する配列を参照せずに新しい配列を作成できますfilter

var myArray = [1, 2, 3, 4, 5, 6];

5配列から削除したい場合は、次のようにするだけです。

myArray = myArray.filter(value => value !== 5);

これにより、削除したい値を含まない新しい配列が得られます。したがって、結果は次のようになります。

 [1, 2, 3, 4, 6]; // 5 has been removed from this array

詳細については、Array.filterの MDNドキュメントを参照してください


21

より近代的なECMAScript 2015(旧称HarmonyまたはES 6)アプローチ。与えられた:

const items = [1, 2, 3, 4];
const index = 2;

次に:

items.filter((x, i) => i !== index);

収量:

[1, 2, 4]

あなたは使用することができバベルポリフィルサービスをこれがうまくブラウザでサポートされていることを確認します。


4
.filterは、新しい配列を返すことに注意してください。これは、同じ配列から要素を削除することとまったく同じではありません。このアプローチの利点は、配列メソッドをチェーンできることです。例:[1,2,3].filter(n => n%2).map(n => n*n) === [ 1, 9 ]
CodeOcelot 2016年

すばらしい、配列に600kの要素があり、最初の50kを削除したい場合、その速度低下を想像できますか?これは解決策ではありません。要素を削除して何も返さない関数が必要です。
dev1223

@Seraphそのためには、おそらくspliceまたはを使用する必要がありsliceます。
bjfletcher 2016年

@bjfletcherそれはさらに良いことであり、削除の過程で、50Kの要素を割り当て、どこかにそれらを投げるだけです。(スライス550K要素を使用しますが、ウィンドウからそれらをスローしません)。
dev1223

私はbjfletcherの答えを好みitems= items.filter(x=>x!=3)ます。その上、OPは大規模なデータセットの要件を述べていませんでした。
runun

21

配列に1から9があり、5を削除します。以下のコードを使用します。

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return m !== 5;
});

console.log("new Array, 5 removed", newNumberArray);


複数の値にしたい場合。例:-1,7,8

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return (m !== 1) && (m !== 7) && (m !== 8);
});

console.log("new Array, 1,7 and 8 removed", newNumberArray);


配列内の配列値を削除する場合。例:[3,4,5]

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var removebleArray = [3,4,5];

var newNumberArray = numberArray.filter(m => {
    return !removebleArray.includes(m);
});

console.log("new Array, [3,4,5] removed", newNumberArray);

サポートされているブラウザが含まれているリンクです。


19

私はすでに多くの答えがあることを知っていますが、それらの多くは問題を過度に複雑にしているようです。キーのすべてのインスタンスを削除する簡単な再帰的な方法を次に示します。インデックスが見つからなくなるまで自分自身を呼び出します。はい、これはを使用するブラウザでのみ機能しますがindexOf、シンプルで簡単にポリフィルできます。

スタンドアロン機能

function removeAll(array, key){
    var index = array.indexOf(key);

    if(index === -1) return;

    array.splice(index, 1);
    removeAll(array,key);
}

プロトタイプ方式

Array.prototype.removeAll = function(key){
    var index = this.indexOf(key);

    if(index === -1) return;

    this.splice(index, 1);
    this.removeAll(key);
}

ちなみに、この方法の1つの注意点は、スタックオーバーフローの可能性です。大規模なアレイを使用しているのでない限り、問題はないはずです。
wharding28

しかし、なぜ真ん中に戻るのですか?これは事実上gotoステートメントです。
Peter Mortensen

18

要素のインスタンスが複数ある場合は、逆方向ループを実行して、インデックスを台無しにしないようにすることができます。

var myElement = "chocolate";
var myArray = ['chocolate', 'poptart', 'poptart', 'poptart', 'chocolate', 'poptart', 'poptart', 'chocolate'];

/* Important code */
for (var i = myArray.length - 1; i >= 0; i--) {
    if (myArray[i] == myElement) myArray.splice(i, 1);
}

ライブデモ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.