オブジェクトプロパティに基づいて配列要素を削除する


271

私は次のようなオブジェクトの配列を持っています:

var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];

プロパティに基づいて特定のものを削除するにはどうすればよいですか?

たとえば、フィールドプロパティとして「money」を含む配列オブジェクトをどのように削除しますか?

回答:


384

1つの可能性:

myArray = myArray.filter(function( obj ) {
    return obj.field !== 'money';
});

filter新しいアレイが作成されることに注意してください。元の変数myArrayを新しい参照で更新しても、元の配列を参照する他の変数はフィルターされたデータを取得しません。注意して使用してください。


6
filter()Internet Explorer 9以降でのみ利用可能であることに注意してください
jessegavin 2013

@jessegavin確かに。私は、機能を模倣した多くの優れたes5シムライブラリが利用できることを述べたはずです(レガシーブラウザをサポートしたい場合に備えて)
jAndy

3
filter()新しい配列を作成します。変数を再割り当てでき、それを参照するコードの他の領域がないことがわかっている場合は問題ありません。これは、元の配列オブジェクトを変更する必要がある場合には機能しません。
ブライアングリック2014

2
配列がツリー構造の場合は、ar beforeDeleteOperationArray = [{"id":3.1、 "name": "test 3.1"、 "activityDetails":[{"id":22、 "name": "test 3.1"}、 {"id":23、 "name": "changed test 23"}]}]そして、id:23を削除したい
forgottofly

@forgottofly良い点-答えは限られた場合にのみ機能します。あなたの質問に対する答えは見つかりましたか?
JackTheKnife

88

配列を反復処理し、不要spliceなものを除外します。使いやすくするために、逆方向に反復処理するので、配列の実際の性質を考慮する必要はありません。

for (var i = myArray.length - 1; i >= 0; --i) {
    if (myArray[i].field == "money") {
        myArray.splice(i,1);
    }
}

3
アレイのライブの性質とはどういう意味ですか?@Neit the Dark Absol
sisimh

29
@sisimh彼は、反復ロジックの一部としてその長さを使用して配列を前方に反復し、要素が削除または追加されたために長さが変化する場合、配列の最後から実行されたり、操作を実行できなくなる可能性があることを意味します配列内のすべてのアイテム。逆方向に移動すると、移動長ではなく静的0インデックスに向かって機能するため、その可能性ははるかに低くなります。
Klors、2015

2
配列がツリー構造の場合は、ar beforeDeleteOperationArray = [{"id":3.1、 "name": "test 3.1"、 "activityDetails":[{"id":22、 "name": "test 3.1"}、 {"id":23、 "name": "changed test 23"}]}]そして、id:23を削除したい
forgottofly

ちょっと明白ですが、単一の一意の要素のみを削除することを期待している場合は、パフォーマンスのために「if」ステートメントにブレークをスローして、ループが残りの配列を不必要に反復しないようにすることができます。
Patrick Borkowicz 2017年

@Klors説明してくれてありがとう。答えのように常に配列を逆に読むのは良いことですか?
kittu

38

フィールドプロパティで2番目のオブジェクトを削除するとします。

ES6では、これと同じくらい簡単です。

myArray.splice(myArray.findIndex(item => item.field === "cStatus"), 1)

7
私はこれを試しましたが、OPの配列から3番目の項目を「削除」する代わりに、コードが「フィルタリング」され、3番目の項目のみが表示されました。
Compaq LE2202x 2018

1
@ CompaqLE2202x 2年後、それはおそらくすでに明らかですが、将来の開発者にとっては:splice元の配列を変更するため、返される値は削除された項目ですが、次に見た場合myArray、項目は失われます。
David Mulder

17

lodashのfindIndexを使用して特定の要素のインデックスを取得し、それを使用してスプライスできます。

myArray.splice(_.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);

更新

ES6のfindIndex()を使用することもできます

findIndex()メソッドは、指定されたテスト関数を満たす配列の最初の要素のインデックスを返します。それ以外の場合は-1が返されます。

myArray.splice(myArray.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);

配列はツリー構造ですか?
2017年

@forgottoflyツリー構造?myArrayここにオブジェクトの配列があると思います。
Sridhar

4
配列がツリー構造の場合var beforeDeleteOperationArray = [{"id":3.1、 "name": "test 3.1"、 "activityDetails":[{"id":22、 "name": "test 3.1"}、 {"id":23、 "name": "changed test 23"}]}]そして、id:23を削除したい
forgottofly

9

jQuery grepを使用する別のオプションを次に示します。true関数に一致する項目をgrepが確実に削除するように、3番目のパラメーターとして渡します。

users = $.grep(users, function(el, idx) {return el.field == "money"}, true)

すでにjQueryを使用している場合は、shimは必要ありません。これは、を使用するのではなく便利ですArray.filter



3

以下は、jQueryを使用していない場合のコードです。デモ

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];

alert(myArray.length);

for(var i=0 ; i<myArray.length; i++)
{
    if(myArray[i].value=='money')
        myArray.splice(i);
}

alert(myArray.length);

たくさんの機能を備えたアンダースコアライブラリを使用することもできます。

Underscoreは、関数型プログラミングサポートの多くを提供するJavaScriptのユーティリティベルトライブラリです。


5
これはWebに残すのは非常に危険な例です...サンプルデータでは機能しますが、それ以外では機能しません。splice(i)は、値がmoneyである最初のインスタンス以降で配列内のすべての要素を削除することを意味します。splice(i、1)に変更した場合、次の順次項目を評価しないため、依然として正しくありません(iもデクリメントする必要があります)。これが、配列の削除操作を逆方向に処理して、 itemは次に処理するアイテムのインデックスを変更しません
Chris Schaller

3
var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];
console.log(myArray.length); //3
myArray = $.grep(myArray, function(element, index){return element.field == "money"}, true);
console.log(myArray.length); //2

要素は配列内のオブジェクトです。第3パラメータtrueは、関数ロジックにfalse失敗する要素の配列を返すことを意味し、関数ロジックに失敗する要素の配列を返すことを意味します。


3

以下のいくつかのコメントに基づいて、キー名とキー値に基づいてオブジェクトを削除する方法のコードです

 var items = [ 
  { "id": 3.1, "name": "test 3.1"}, 
  { "id": 22, "name": "test 3.1" }, 
  { "id": 23, "name": "changed test 23" } 
  ]

    function removeByKey(array, params){
      array.some(function(item, index) {
        return (array[index][params.key] === params.value) ? !!(array.splice(index, 1)) : false;
      });
      return array;
    }

    var removed = removeByKey(items, {
      key: 'id',
      value: 23
    });

    console.log(removed);

3

lodashライブラリの使用:

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];
var newArray = _.remove(myArray, function(n) {
  return n.value === 'money';;
});
console.log('Array');
console.log(myArray);
console.log('New Array');
console.log(newArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>


1

jAndyの解決策はおそらく最良ですが、フィルターに依存できない場合は、次のようなことができます。

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: "money"}
];

myArray.remove_key = function(key){
    var i = 0, 
        keyval = null;
    for( ; i < this.length; i++){
        if(this[i].field == key){
            keyval = this.splice(i, 1);
            break;
        }
    }
    return keyval;
}

1
filter()に依存できないのはなぜですか?
imperium2335 2013年

2
これはJavaScript 1.6の一部であり、IE8以前のブラウザーではサポートされていません。
Rob M.

-1

lodashライブラリを使用すると、このように簡単です

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