从对象数组中删除元素javascript

Posted

技术标签:

【中文标题】从对象数组中删除元素javascript【英文标题】:Remove element from array of objects javascript 【发布时间】:2017-03-21 23:30:09 【问题描述】:

我有以下对象数组。

["rId":24,"gId":40,"sId":20,"disabled":false,
 "rId":24,"gId":40,"sId":19,"disabled":false,
 "rId":24,"gId":40,"sId":50,"disabled":false,
 "rId":24,"gId":40,"sId":20,"disabled":true,
 "rId":24,"gId":40,"sId":19,"disabled":true,
 "rId":24,"gId":40,"sId":50,"disabled":true,
 "rId":24,"gId":39,"sId":18,"disabled":false]

其中一些记录是对立的。第一个元素和第四个元素具有相同的 rId、gId 和 sId 但禁用标志相反。 我想消除所有这些记录。

我的预期数组是"rId":24,"gId":39,"sId":18,"disabled":false(消除所有对立记录)

我尝试了以下代码,但它给了我错误的输出。

arrOfObj=["rId":24,"gId":40,"sId":20,"disabled":false,
 "rId":24,"gId":40,"sId":19,"disabled":false,
 "rId":24,"gId":40,"sId":50,"disabled":false,
 "rId":24,"gId":40,"sId":20,"disabled":true,
 "rId":24,"gId":40,"sId":19,"disabled":true,
 "rId":24,"gId":40,"sId":50,"disabled":true,
 "rId":24,"gId":39,"sId":18,"disabled":false]


$.each(arrOfObj,function (index1,firstObj) 
    $.each(arrOfObj,function (index2,secondObj) 
        if(index1>= index2)
            return true;
        
        var areObjAntithesis=firstObj.rId===secondObj.rId && firstObj.gId===secondObj.gId
           && firstObj.sId===secondObj.sId && firstObj.disabled!==secondObj.disabled;

        if(areObjAntithesis)
            arrOfObj.splice(index1,1);
            arrOfObj.splice(index2,1)
            return false;
        
    )
)

有什么优雅的方法可以达到预期的输出吗?

【问题讨论】:

【参考方案1】:

您可以使用 map()filter() 来做到这一点

var data = ["rId":24,"gId":40,"sId":20,"disabled":false,
 "rId":24,"gId":40,"sId":19,"disabled":false,
 "rId":24,"gId":40,"sId":50,"disabled":false,
 "rId":24,"gId":40,"sId":20,"disabled":true,
 "rId":24,"gId":40,"sId":19,"disabled":true,
 "rId":24,"gId":40,"sId":50,"disabled":true,
 "rId":24,"gId":39,"sId":18,"disabled":false]
 
var ar = data.map(function(e) 
  return e.rId + '|' + e.gId + '|' + e.sId;
);
 
var result = data.filter(function(e) 
  var key = e.rId + '|' + e.gId + '|' + e.sId;
  return ar.indexOf(key) == ar.lastIndexOf(key);
);

console.log(result)

【讨论】:

【参考方案2】:

使用http://underscorejs.org/#where 并这样做:

var newArrOfObj=_.where(arrOfObj, disabled:true);

【讨论】:

【参考方案3】:

您可以使用多个array.filter 并检查计数,并且仅返回值超过 1 个且值相同或只有一个值的元素

var data = ["rId":24,"gId":40,"sId":20,"disabled":false,
 "rId":24,"gId":40,"sId":19,"disabled":false,
 "rId":24,"gId":40,"sId":50,"disabled":false,
 "rId":24,"gId":40,"sId":20,"disabled":true,
 "rId":24,"gId":40,"sId":19,"disabled":true,
 "rId":24,"gId":40,"sId":50,"disabled":true,
 "rId":24,"gId":39,"sId":18,"disabled":false]

var result = data.filter(function(outer)
  var disablesValues = []
  
  var _r = data.filter(function(inner)
    if(inner.gId === outer.gId && inner.sId === outer.sId)
      if(disablesValues.indexOf(inner.disabled) < 0)
        disablesValues.push(inner.disabled);
      return true;
    
  );
  
  return _r.length === 1 || disablesValues.length === 1
);

console.log(result)

【讨论】:

【参考方案4】:

这是函数式编程风格的 ES6 解决方案,它也将处理更多的重复,计算禁用和启用对象的数量如何相互平衡:

function eliminateOpposites(arr) 
    return [...arr
        .map( o => ( o, k: JSON.stringify( rId:o.rId, gId:o.gId, sId:o.sId ) ) )
        .reduce( (acc, o) => acc.set(o.k, (acc.get(o.k) || 0)+ (+o.o.disabled || -1)),
                             new Map() )]
        .filter( ([k, balance]) => balance )
        .map( ([k, balance]) => Object.assign(JSON.parse(k), disabled: balance>0));


// Sample data
var arrOfObj=[
 "rId":24,"gId":40,"sId":20,"disabled":false,
 "rId":24,"gId":40,"sId":19,"disabled":false,
 "rId":24,"gId":40,"sId":50,"disabled":false,
 "rId":24,"gId":40,"sId":20,"disabled":true,
 "rId":24,"gId":40,"sId":19,"disabled":true,
 "rId":24,"gId":40,"sId":50,"disabled":true,
 "rId":24,"gId":39,"sId":18,"disabled":false]
 
console.log(eliminateOpposites(arrOfObj));

它利用散列,这导致 O(n) 算法而不是 O(n²)indexOf 风格的解决方案就是这种情况.

JSON.stringifyJSON.parse 用于组合和分解组合键值。字符串版本用作Map 中的键,其中每个条目记录相同键的禁用与启用次数。 .filter() 调用排除了禁用和启用的次数相同的情况(可能是 2 对 2),最后的 .map() 将 kay/value 数组转换回预期的格式。

【讨论】:

【参考方案5】:

您可以使用两个循环,一个用于收集数组,一个用于过滤数组。

var data = [ "rId": 24, "gId": 40, "sId": 20, "disabled": false ,  "rId": 24, "gId": 40, "sId": 19, "disabled": false ,  "rId": 24, "gId": 40, "sId": 50, "disabled": false ,  "rId": 24, "gId": 40, "sId": 20, "disabled": true ,  "rId": 24, "gId": 40, "sId": 19, "disabled": true ,  "rId": 24, "gId": 40, "sId": 50, "disabled": true ,  "rId": 24, "gId": 39, "sId": 18, "disabled": false ],
    hash = Object.create(null),
    getKey = function (o)  return ["rId", "gId", "sId"].map(function (k)  return o[k]; ).join('|'); ,
    result;

data.forEach(function (a) 
    var key = getKey(a);
    hash[key] = (hash[key] || 0) + (a.disabled || -1);
);

result = data.filter(function (a) 
    return hash[getKey(a)];
);

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

ES6 与 Array#find

var data = [ "rId": 24, "gId": 40, "sId": 20, "disabled": false ,  "rId": 24, "gId": 40, "sId": 19, "disabled": false ,  "rId": 24, "gId": 40, "sId": 50, "disabled": false ,  "rId": 24, "gId": 40, "sId": 20, "disabled": true ,  "rId": 24, "gId": 40, "sId": 19, "disabled": true ,  "rId": 24, "gId": 40, "sId": 50, "disabled": true ,  "rId": 24, "gId": 39, "sId": 18, "disabled": false ],
    result = data.filter(a =>
        !data.find(b => ["rId", "gId", "sId"].every(k => 
            a[k] === b[k]
        ) && a.disabled !== b.disabled));

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

以上是关于从对象数组中删除元素javascript的主要内容,如果未能解决你的问题,请参考以下文章

javascript中,知道一个值,如何删除数组中的这个值的元素。

javascript删除数组/对象中的元素

08.18 javascript 06 数组 数组的概念 创建数组 读取数组中的元素 稀疏数组 添加和删除数组的元素 数组遍历 多维数组 数组的方法 类数组对象 作为数组的字符串

删除对象数组中的重复元素Javascript [关闭]

JavaScript 浅析数组对象与类数组对象

jQuery / Javascript从对象数组中删除一个对象[重复]