【问题标题】:Remove array element based on object property根据对象属性删除数组元素
【发布时间】:2013-02-23 15:15:19
【问题描述】:

我有一个这样的对象数组:

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

如何根据属性删除特定的?

例如如何删除以 'money' 作为字段属性的数组对象?

【问题讨论】:

    标签: javascript jquery arrays object properties


    【解决方案1】:

    一种可能性:

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

    请注意filter 会创建一个新数组。尽管您使用新引用更新原始变量myArray,但引用原始数组的任何其他变量都不会获得过滤后的数据。谨慎使用。

    【讨论】:

    • 请注意,filter() 仅适用于 Internet Explorer 9+
    • @jessegavin 确实如此。我应该提到有很多好的 es5 shim 库可用,它们模仿了功能(以防万一你想支持旧版浏览器)
    • filter() 创建一个新数组,如果您能够重新分配变量并且知道没有其他代码区域引用它,那么这很好。如果您特别需要修改原始数组对象,这将不起作用。
    • 如果数组是树形结构 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 好点 - 答案仅适用于有限的情况。您找到问题的答案了吗?
    【解决方案2】:

    遍历数组,然后splice 找出你不想要的。为了更容易使用,向后迭代,这样您就不必考虑数组的实时特性:

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

    【讨论】:

    • 阵列的实时特性是什么意思? @Neit the Dark Absol
    • @sisimh 他的意思是,如果您通过使用数组的长度作为迭代逻辑的一部分来向前迭代数组,并且由于删除或添加了元素而导致其长度发生变化,您最终可能会跑到数组或不对数组中的每个项目执行操作。向后退的可能性要小得多,因为它朝着静态 0 索引而不是移动长度工作。
    • 如果数组是树形结构 ar beforeDeleteOperationArray=[ { "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name ": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] } ] 我想删除 id:23
    • 有点明显,但如果您只希望删除单个唯一元素,您可以在“if”语句中插入一个中断以提高性能,这样循环就不会不必要地遍历数组的其余部分.
    • @Klors 感谢您的解释。总是像答案一样向后读取数组是否很好?
    【解决方案3】:

    假设您想通过它的字段属性删除第二个对象。

    使用 ES6 就这么简单。

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

    【讨论】:

    • 我试过了,但不是从 OP 的数组中“删除”第三项,而是您的代码“过滤”并仅显示第三项。
    • @CompaqLE2202x 2 年后可能对您来说已经很明显了,但对于未来的开发人员:splice 更改了原始数组,因此您返回的值是被删除的项目,但如果您下一个看看myArray,该项目将丢失。
    • 如果findIndex没有找到该元素,则返回-1,并通过splice删除最后一个元素,尽管它与谓词不匹配。
    【解决方案4】:

    在 ES6 中,只有一行。

    const arr = arr.filter(item => item.key !== "some value");
    

    :)

    【讨论】:

    • 请记住,过滤器会创建一个新数组。
    【解决方案5】:

    你可以使用lodash的findIndex获取特定元素的索引,然后使用它进行拼接。

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

    更新

    你也可以使用 ES6 的findIndex()

    findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回 -1。

    const itemToRemoveIndex = myArray.findIndex(function(item) {
      return item.field === 'money';
    });
    
    // proceed to remove an item only if it exists.
    if(itemToRemoveIndex !== -1){
      myArray.splice(itemToRemoveIndex, 1);
    }
    

    【讨论】:

    • 什么是数组是树结构?
    • @forgottofly 树结构?我认为myArray 这里是一个对象数组。
    • 如果数组是树结构怎么办 var beforeDeleteOperationArray=[ { "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name ": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] } ] 我想删除 id:23
    • 如果findIndex(ES6版本)没有找到该元素,则返回-1,并通过splice删除最后一个元素,尽管它与谓词不匹配。
    • @Yannic 不错。感谢您指出。更新了我的答案。
    【解决方案6】:

    这是另一个使用 jQuery grep 的选项。将true 作为第三个参数传递,以确保 grep 删除与您的函数匹配的项目。

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

    如果您已经在使用 jQuery,则不需要 shim,这与使用 Array.filter 相比可能有用。

    【讨论】:

      【解决方案7】:

      我们可以使用以下两种方法根据属性删除元素。

      1. 使用过滤方法
      testArray.filter(prop => prop.key !== 'Test Value')
      
      1. 使用拼接方法。对于这种方法,我们需要找到属性的索引。
      const index = testArray.findIndex(prop => prop.key === 'Test Value')
      testArray.splice(index,1)
      

      【讨论】:

        【解决方案8】:
        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
        

        元素是数组中的一个对象。 第三个参数true 表示将返回一个不符合您的功能逻辑的元素数组,false 表示将返回一个不符合您的功能逻辑的元素数组。

        【讨论】:

          【解决方案9】:

          基于上面的一些cmets,下面是如何根据键名和键值删除对象的代码

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

          【讨论】:

            【解决方案10】:

            使用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>

            【讨论】:

              【解决方案11】:

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

              【讨论】:

              • 为什么我不能依赖 filter()?
              • 因为它是 JavaScript 1.6 的一部分,IE8 及更低版本或更旧的浏览器不支持。
              【解决方案12】:

              如果您不使用 jQuery,以下是代码。 Demo

              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 的实用工具带库,提供了很多函数式编程支持

              【讨论】:

              • 这是一个留在网络上的非常危险的示例......它适用于示例数据,但不适用于其他任何数据。 splice(i) 意味着它将删除数组中从 value 是 money 的第一个实例开始和之后的所有元素,这根本不满足 op 的要求。如果我们更改为 splice(i,1) 它仍然是不正确的,因为它不会评估下一个顺序项(您也必须递减 i)这就是为什么您应该向后处理数组中的删除操作,以便删除一个item 不会改变下一个要处理的项目的索引
              猜你喜欢
              • 2013-05-17
              • 1970-01-01
              • 2018-09-12
              • 2016-11-08
              • 1970-01-01
              • 2020-04-28
              • 2015-12-07
              • 1970-01-01
              相关资源
              最近更新 更多