根据创建时间从对象数组中删除重复项

3

我有一个对象数组,其中有一些重复的对象

const data = [
{
    "id": "1011",
    "name": "abc",
    "Dob": "3/2/11",
    "timeCreated": "16:03:41"
},
{
    "id": "1012",
    "name": "xys",
    "Dob": "6/5/12",
    "timeCreated": "01:05:21"
},
{
    "id": "1011",
    "name": "xyz",
    "Dob": "3/2/11",
    "timeCreated": "17:03:41"
},
{
    "id": "1011",
    "name": "xyz",
    "Dob": "3/2/11",
    "timeCreated": "15:03:41"
}
]

我正在使用some()方法来删除数组中的重复项。

let arr = [];
data.forEach(obj => {
  if (!arr .some(o => o.id === obj.id)) {
    arr.push({ ...obj})
  }
});   

我需要帮助对数据进行过滤,并仅保留基于" timeCreated "的最新对象。

因此,数据看起来像这样:

{
    "id": "1012",
    "name": "xys",
    "Dob": "6/5/12",
    "timeCreated": "01:05:21"
},
{
    "id": "1011",
    "name": "xyz",
    "Dob": "3/2/11",
    "timeCreated": "17:03:41"
},
]

Dob 中的日期不算吗? - Mister Jojo
我的实际数据中不包括 Dob,我只是加上它因为我想不到其他的内容,但我需要帮助的唯一事情就是确保它删除旧日期并保留最近日期。 - Sam Lock
2个回答

3
你可以这样做:

const data = 
  [ { id: '1011', name: 'abc', Dob: '3/2/11', timeCreated: '16:03:41' } 
  , { id: '1012', name: 'xys', Dob: '6/5/12', timeCreated: '01:05:21' } 
  , { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '17:03:41' } 
  , { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '15:03:41' } 
  ] 

const arr = data.reduce((result,obj)=>
  {
  let row = result.find(x=>x.id===obj.id)
  if (!row)
         result.push({...obj})
  else if (row.timeCreated < obj.timeCreated)
         Object.assign(row,obj)
  return result
  },[])

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


1
来晚了,但这里有一个更短、可能更快、更有效的解决方案,只涉及排序和过滤操作。
let tmp=[], arr = data.sort((a, b) => +b.timeCreated.replaceAll(':', '') - +a.timeCreated.replaceAll(':', ''))
            .filter(o => (!tmp.includes(o.id) && tmp.push(o.id)));
它是如何工作的:实际上非常简单。首先按时间创建的降序对数组进行排序。它通过(即时)将“HH:MM:SS”字符串转换为数字HHMMSS(+b.timeCreated.replaceAll(':', '')),然后进行比较来实现这一点。然后它将已排序的数组过滤到临时数组tmp中,该数组在每次迭代中存储ids - 如果该id已经存在(并且我们知道根据timeCreated它是最新的),则将其过滤掉。这全部由神奇简单的三元运算符处理:.filter(o => (!tmp.includes(o.id) && tmp.push(o.id)),它表示如果我们已经看到了该id,则返回false,否则记下它

为什么很酷 - 对于大多数用例(小数据集),像map、reduce、forEach、filter、sort这样的函数式迭代器之间没有显著的区别 - 然而,这是超越传统思维的。它不是先构建数据集再将其缩小,而是智能地先将其切割到合适的大小 - 只使用了2个操作。

const data = [{ id: '1011', name: 'abc', Dob: '3/2/11', timeCreated: '16:03:41' }, { id: '1012', name: 'xys', Dob: '6/5/12', timeCreated: '01:05:21' }, { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '17:03:41' }, { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '15:03:41' }]
let tmp=[], arr = data.sort((a, b) => +b.timeCreated.replaceAll(':', '') - +a.timeCreated.replaceAll(':', '')).filter(o => (!tmp.includes(o.id) && tmp.push(o.id)));
    
console.log(arr)


请简要解释一下 filter 中正在发生的事情。 - Sam Lock
@SamLock 我更新了我的回答,并附上了(稍微自我夸耀的)解释 :) - Kinglish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接