从对象数组中删除元素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.stringify
和JSON.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中,知道一个值,如何删除数组中的这个值的元素。
08.18 javascript 06 数组 数组的概念 创建数组 读取数组中的元素 稀疏数组 添加和删除数组的元素 数组遍历 多维数组 数组的方法 类数组对象 作为数组的字符串