Typescript 按对象id高效地获取唯一列表

Typescript 按对象id高效地获取唯一列表,typescript,time-complexity,Typescript,Time Complexity,我有一系列的项目。每个项目都有一组员工。每个员工都有一个唯一的标识符id。我希望将所有项目中的所有员工合并到一个数组中,但删除重复项 我考虑先创建一个映射,密钥是员工id。这样我可以检查映射是否已经将员工id作为密钥,并且只有在不存在以下情况时才将其添加到映射中: this.projects.forEach(project => { project.employees.forEach(employee=> { if (!this.employeeIdToEmployeeM

我有一系列的
项目
。每个
项目
都有一组
员工
。每个员工都有一个唯一的标识符
id
。我希望将所有
项目
中的所有
员工
合并到一个数组中,但删除重复项

我考虑先创建一个
映射
,密钥是员工id。这样我可以检查映射是否已经将员工
id
作为密钥,并且只有在不存在以下情况时才将其添加到映射中:

this.projects.forEach(project => {
  project.employees.forEach(employee=> {
    if (!this.employeeIdToEmployeeMap.has(employee.id)) {
      this.employeeIdToEmployeeMap.set(employee.id, employee);
    }
  })
});
之后,我可以获取地图的值并将其转换为数组:

this.employees = Array.from(this.employeeIdToEmployeeMap.values());
现在我有了所有
项目的所有
员工
,没有任何重复


有更好的方法吗?可以在O(n)中完成吗?

您可以使用reduce方法来实现:

const projects: { employees: { id: any }[] }[] = [
    { employees: [{ id: 2 }, { id: 7 }] },
    { employees: [{ id: 5 }, { id: 7 }] }
];

const map = projects.reduce((employees, project) => ({
    ...employees,
    ...project.employees.reduce((emps, employee) => ({
        ...emps,
        ...(emps[employee.id] ? {} : { [employee.id]: employee })
    }), employees as any)
}), {} as any)

console.log(Object.values(map)); // Prints: [ {id: 2}, {id: 5}, {id: 7}

您可以使用reduce方法来实现以下目标:

const projects: { employees: { id: any }[] }[] = [
    { employees: [{ id: 2 }, { id: 7 }] },
    { employees: [{ id: 5 }, { id: 7 }] }
];

const map = projects.reduce((employees, project) => ({
    ...employees,
    ...project.employees.reduce((emps, employee) => ({
        ...emps,
        ...(emps[employee.id] ? {} : { [employee.id]: employee })
    }), employees as any)
}), {} as any)

console.log(Object.values(map)); // Prints: [ {id: 2}, {id: 5}, {id: 7}
有一个简单的O(nlogn)解决方案:

  • 把所有员工都列在一张名单上
  • 对列表排序
  • 将员工添加到新列表,同时跳过连续的重复项
  • 您的解决方案有多复杂?好吧,如果给定映射的任何合理实现,那么将映射转换为列表应该是O(n)。外部循环体执行n次。所以,问题是,向映射添加元素意味着什么复杂性?最坏情况下的时间显然是线性的(假设基于列表的bucket和开放散列;如果使用树或其他东西,则可能是log(n)),最佳情况下的时间是恒定的。在这里,因为我们的问题基本上是将n个项目放入一个映射中,所以我们需要知道摊销的复杂性。当检测到空间不足时,使用可调整大小的后备存储和乘法扩展,我希望可以为add操作获得O(1)分摊的复杂性。如果这就是映射的工作方式,那么您所拥有的就是O(1)假设一个好的哈希函数。

    有一个简单的O(nlogn)解决方案:

  • 把所有员工都列在一张名单上
  • 对列表排序
  • 将员工添加到新列表,同时跳过连续的重复项
  • 您的解决方案有多复杂?好吧,如果给定映射的任何合理实现,那么将映射转换为列表应该是O(n)。外部循环体执行n次。所以,问题是,向映射添加元素意味着什么复杂性?最坏情况下的时间显然是线性的(假设基于列表的bucket和开放散列;如果使用树或其他东西,则可能是log(n)),最佳情况下的时间是恒定的。在这里,因为我们的问题基本上是将n个项目放入一个映射中,所以我们需要知道摊销的复杂性。当检测到空间不足时,使用可调整大小的后备存储和乘法扩展,我希望可以为add操作获得O(1)分摊的复杂性。如果你的映射就是这样工作的,那么你得到的就是O(1)假设一个好的散列函数