根据多个条件从数组中删除重复的对象

时间:2020-10-13 16:54:58

标签: javascript

我有一个数组arr,我要从中删除具有
的重复对象 _同样e_display_id
_和e_type作为P
在这种情况下,我只想考虑带有status==='N'的对象。

下面是输入数组arr:

let arr = 
  [ { e_type: "P", e_record_id: 33780, e_display_id: "EA-15-001", status: "Y" } 
  , { e_type: "P", e_record_id: 33744, e_display_id: "PE-14-016", status: "N" } 
  , { e_type: "P", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
  , { e_type: "P", e_record_id:   420, e_display_id: "PE-14-911", status: "Y" } 
  , { e_type: "P", e_record_id:   421, e_display_id: "PE-14-911", status: "N" } 
  , { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
  , { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
  ];

我当前的实现方式:

我正在使用loadash方法将e_type过滤为P
然后检查是否有重复的e_display_id
如果仅存在,则仅将具有status的那个视为N

let   clonedPursuits  = [...arr];
let   myarr           = _.filter(clonedPursuits, x => x.e_type === 'P');
const counts          = _.countBy(myarr, 'e_display_id');
  clonedPursuits      = _.filter(myarr, x => counts[x.e_display_id] > 1);
const uniqueAddresses = Array.from(new Set(clonedPursuits.map(a => a.e_display_id)))
                          .map(id => {
                 return clonedPursuits.find(a => a.e_display_id === id && a.status === "N");
                           });
console.log( uniqueAddresses );

预期输出:

[ { e_type: "P", e_record_id: 33780, e_display_id: "EA-15-001", status: "Y" } 
, { e_type: "P", e_record_id: 33744, e_display_id: "PE-14-016", status: "N" } 
, { e_type: "P", e_record_id:   421, e_display_id: "PE-14-911", status: "N" } 
, { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
, { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
];

当前输出:

[ { e_type: "P", e_record_id: 33744, e_display_id: "PE-14-016", status: "N"} 
, { e_type: "P", e_record_id:   421, e_display_id: "PE-14-911", status: "N"} 
] 

2 个答案:

答案 0 :(得分:0)

我已经做到了:

const arr = 
  [ { e_type: "P", e_record_id: 33780, e_display_id: "EA-15-001", status: "Y" } 
  , { e_type: "P", e_record_id: 33744, e_display_id: "PE-14-016", status: "N" } 
  , { e_type: "P", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" }
  , { e_type: "P", e_record_id:   420, e_display_id: "PE-14-911", status: "Y" }
  , { e_type: "P", e_record_id:   421, e_display_id: "PE-14-911", status: "N" } 
  , { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
  , { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
  ] 

const res = arr.reduce((a,c,i,t)=>
  {
  if (c.e_type!=='P')
    a.push({...c})
  else
    {
    if (c.status==='N')
      a.push({...c})
    else if (!t.some(x=> x.e_type==='P' && x.e_display_id===c.e_display_id  && x.status==='N' ))
      a.push({...c})
    }
  return a
  },[])

console.log( res )

console.log( ' --------- original array direct removing:-----------------')
// If you prefer to delete the elements directly without creating another array:

for(let i=arr.length;i--;)
  {
  let c = arr[i]
  if (c.e_type!=='P') continue
  if (c.status==='N') continue
  if (!arr.some(x=> x.e_type==='P' && x.e_display_id===c.e_display_id  && x.status==='N' )) continue
  arr.splice(i,1)
  }
console.log(  arr )
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:0)

我认为这应该为您做。该解决方案的优点在于,它最多只能(最多)两次通过项数组,这意味着它具有O(n)的时间复杂度,因此非常高效。此解决方案的缺点是,它不保留项目的顺序,因此,如果顺序很重要,则需要重新排序它们,这使解决方案O(nlog(n))

此解决方案背后的想法是,将您知道的项目添加到项目列表的第一遍中,同时还要跟踪看到的e_display_id及其状态。然后第二次遍历数据(反复查看已看到但未添加的内容),您将立即知道根据规则需要添加哪些内容。

let arr = [ 
  { e_type: "P", e_record_id: 33780, e_display_id: "EA-15-001", status: "Y" },
  { e_type: "P", e_record_id: 33744, e_display_id: "PE-14-016", status: "N" },
  { e_type: "P", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" },
  { e_type: "P", e_record_id:   420, e_display_id: "PE-14-911", status: "Y" },
  { e_type: "P", e_record_id:   421, e_display_id: "PE-14-911", status: "N" },
  { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" },
  { e_type: "R", e_record_id: 33386, e_display_id: "PE-14-016", status: "Y" } 
];

let seen = {};

let filtered = arr.reduce((res, curr) => {
  let type = curr.e_type;
  let status = curr.status;
  let id = curr.e_display_id;
  if (type !== "P") {
    // if type is not "P", we add it unconditionally
    res.push(curr);
  }
  else {
    if (!seen[id]) { seen[id] = {}; }
    if (!seen[id][status]) { seen[id][status] = []; }
    // add to "seen" list for status "N" or "Y" for this e_display_id 
    // so we can decide later whether to keep it or throw it away
    seen[id][status].push(curr);
  }
  return res;
}, [])

// add the e_type = "P" items in to final results based on e_display_id
let finalResults = filtered.concat(Object.values(seen).reduce((res, curr) => {
  // keep Ns, regardless if there are multiples for that e_display_id
  if (curr["N"]) { res.push(...curr["N"]); } 
  // if no Ns, keep Ys as long as no duplicates, 
  // meaning only 1 item in "seen" array for this e_display_id
  else if (curr["Y"] && curr["Y"].length === 1) { res.push(...curr["Y"]); }
  return res;
}, []))

console.log(finalResults);