Javascript 如何基于对象中的属性合并对象数组中的对象

Javascript 如何基于对象中的属性合并对象数组中的对象,javascript,arrays,object,ecmascript-6,Javascript,Arrays,Object,Ecmascript 6,我有一系列的活动,比如 this.activities = [ { id: 54, event_type: 'CA', user_id: 56, user_name: 'Anand', purpose: disregard, timestamp: 14356787 }, { id: 54, event_type: 'NA', user_id: 56, user_name: 'Anand', purpose: 'privacy', timestamp: '' }, { id: 54, event_

我有一系列的活动,比如

this.activities = [
{
id: 54,
event_type: 'CA',
user_id: 56,
user_name: 'Anand',
purpose: disregard,
timestamp: 14356787
},
{
id: 54,
event_type: 'NA',
user_id: 56,
user_name: 'Anand',
purpose: 'privacy',
timestamp: ''
},
{
id: 54,
event_type: 'FA',
user_id: 56,
user_name: 'Anand',
purpose: 'Call',
timestamp: ''
},
{
id: 54,
event_type: 'FA',
user_id: 56,
user_name: 'Anand',
purpose: 'Listen',
timestamp: ''
},
{
id: 54,
event_type: 'CA',
user_id: 56,
user_name: 'Anand',
purpose: 'Not allowed',
timestamp: 14356784
},
{
id: 54,
event_type: 'NA',
user_id: 56,
user_name: 'Anand',
purpose: 'data',
timestamp: 14356786
},
{
id: 54,
event_type: 'CA',
user_id: 56,
user_name: 'Anand',
purpose: 'voicemail',
timestamp: 14356785
},
{
id: 54,
event_type: 'CA',
user_id: 56,
user_name: 'Anand',
purpose: 'phone',
timestamp: 14356775
},
{
id: 54,
event_type: 'CA',
user_id: 56,
user_name: 'Anand',
purpose: 'email',
timestamp: 14356776
},
{
id: 54,
event_type: 'CA',
user_id: 56,
user_name: 'Anand',
purpose: 'letter',
timestamp: 14356777
}
]
我只想根据每个活动的5ms时间戳差异,按事件类型“CA”对该数组进行分组/筛选。因此,如果事件类型为“CA”的活动的时间戳彼此相差不超过5毫秒,则将这些活动加入俱乐部,形成一个新的活动,除了称为“CA联合”的俱乐部活动的新事件类型外,其他所有活动都相同。 所以这个数组应该是这样的

this.activities = [
{
id: 54,
event_type: 'CA_combined',
user_id: 56,
user_name: 'Anand',
purposes: ['disregard', 'Not allowed', 'voicemail'],
timestamp: 14356787
},
{
id: 54,
event_type: 'CA_combined',
user_id: 56,
user_name: 'Anand',
purposes: ['letter','email','phone']
timestamp: 14356777
},
{
id: 54,
event_type: 'NA',
user_id: 56,
user_name: 'Anand',
purpose: 'privacy',
timestamp: ''
},
{
id: 54,
event_type: 'FA',
user_id: 56,
user_name: 'Anand',
purpose: 'Call',
timestamp: ''
},
{
id: 54,
event_type: 'FA',
user_id: 56,
user_name: 'Anand',
purpose: 'Listen',
timestamp: ''
},
{
id: 54,
event_type: 'NA',
user_id: 56,
user_name: 'Anand',
purpose: 'data',
timestamp: 14356786
}
]
我该如何实现这样的目标? 我的尝试到现在为止, 过滤事件类型为CA的所有事件,并根据时间戳值对数组进行排序

let consentActivities = this.activities.filter(c => {
        if (c.event_type === 'CA') {
          return true
        } else {
          return false
        }
      })
consentActivities.sort((a, b) => {
        return b.timestamp - a.timestamp
      })
这就是我不知道如何在5毫秒内组织活动,并且完全失去它的地方

 if (consentActivities.length && consentActivities[0].timestamp - consentActivities[consentActivities.length - 1].timestamp <= 5) {
        consentActivities[0].purposes = []
        consentActivities.forEach((p) => {
          consentActivities[0].purposes.push(p.purpose)
        })
        // consentActivities.splice(1, consentActivities.length)
      }
if(approveActivities.length&&approveActivities[0]。时间戳-approveActivities[approveActivities.length-1]。时间戳{
同意活动[0]。目的。推送(p.purpose)
})
//同意活动.拼接(1,同意活动.长度)
}

非常感谢您的任何输入

您已经采取了正确的第一步:筛选CA、排序,然后您可以通过访问上一个索引轻松分组:

  const entries = data
    .filter(it => it.event_type === "CA")
    .sort((a, b) => a.timestamp - b.timestamp);

 const grouped = [];

 for(const entry of entries) {
   const previous = grouped[grouped.length - 1];
   if(previous && Math.abs(entry.timestamp - previous.timestamp) < 5) {
      previous.purposes.push(entry.purpose);
   } else {
     grouped.push({ id: entry.id, /*...*/, purposes: [entry.purpose] });
   }
}
const entries=数据
.filter(it=>it.event_type==“CA”)
.sort((a,b)=>a.timestamp-b.timestamp);
常量分组=[];
for(条目的常量输入){
const previous=grouped[grouped.length-1];
if(previous&&Math.abs(entry.timestamp-previous.timestamp)<5){
先前的.push(entry.push);
}否则{
push({id:entry.id,/*…*/,目的:[entry.purpose]});
}
}
解决了这个O(n)解决方案

sortedCAarray.forEach((动作,索引)=>{
const currActivityTime=时刻(act.timestamp).valueOf()的值
console.log(currenctivitytime)
//已添加第一个元素,请避免重复
如果(索引<1)返回
//从时间戳映射中获取最后一个键
const timestampKeys=Object.keys(timestampMap)
const key=timestampKeys[timestampKeys.length-1]
//将活动和目的添加到相应的数组中,如果键在当前活动时间戳的5个单位内,则为该键设置
if(数学abs(键-当前活动时间)<5){
让活动=时间戳映射[key]。活动
让purposes=timestampap[key]。purposes
活动推送(act)
目的。添加(法案目的)
让timestamp=moment(活动[activities.length-1].timestamp.valueOf()
//边缘案例包括同一存储桶中的所有活动,如果这些活动在存储桶中任何元素的5ms范围内
如果(时间戳>键){
Object.defineProperty(时间戳映射、时间戳、,
Object.getOwnPropertyDescriptor(timestampMap,key))
删除时间戳映射[键]
}
}否则{
//如果不是,只需创建一个以当前活动时间戳为键的新键
timestampMap[currActivityTime]={activities:[act],目的:新集合([act.purpose])}
}
})

如果您对此有任何改进,我们将不胜感激!谢谢你

你可以试一试。我在编辑中添加了我的尝试,谢谢。感谢您的输入当您合并两个事件时,您有两个时间戳。您将第三个事件与组合事件合并的逻辑是什么?@MaxG如果活动的时间戳在5毫秒以内,请将这些活动合并,并为合并的活动分配最大的时间戳。这回答了你的问题吗?假设三个事件发生在0毫秒、5毫秒和10毫秒。他们都应该分组吗?嗨,乔纳斯,我得到的结果并不像我在问题中提到的那样是期望的输出。我在所有“CA”活动的每个数组中获得一个具有目的的对象数组。我需要的是将5毫秒内的所有活动合并为一个。这意味着我猜我需要在某个点上使用拼接解决这个O(n)解决方案
 sortedCAarray.forEach((act, index) => {
        const currActivityTime = moment(act.timestamp).valueOf()
        console.log(currActivityTime)
        //  First element is already added, avoid duplicates
        if (index < 1) return
        // Grab the last key from the timestampMap
        const timestampKeys = Object.keys(timestampMap)
        const key = timestampKeys[timestampKeys.length - 1]
        // Add the activity and purpose to the respective arrays and set for that key if the key is within 5 units of the current activity timestamp
        if (Math.abs(key - currActivityTime) < 5) {
          let activities = timestampMap[key].activities
          let purposes = timestampMap[key].purposes
          activities.push(act)
          purposes.add(act.purpose)
          let timestamp = moment(activities[activities.length - 1].timestamp).valueOf()
          // Edge case to to include all activities in the same bucket if they were within 5 ms of any element within the bucket
          if (timestamp > key) {
            Object.defineProperty(timestampMap, timestamp,
              Object.getOwnPropertyDescriptor(timestampMap, key))
            delete timestampMap[key]
          }
        } else {
          // If not just create a new key with the current activity timestamp as the key
          timestampMap[currActivityTime] = { activities: [act], purposes: new Set([act.purpose]) }
        }
      })