Javascript 算法+ES6-比较4个对象数组并删除所有重复项

Javascript 算法+ES6-比较4个对象数组并删除所有重复项,javascript,arrays,algorithm,ecmascript-6,Javascript,Arrays,Algorithm,Ecmascript 6,我正在尝试按首选项删除四个数组之间的所有重复对象。所有数组都有唯一的元素,并且可能没有顺序。下面是一张试图解释问题的图片: 如您所见,如果数组具有较低的首选项,则元素将保留在其中。例如,id为6的对象在首选项为2、3和4的数组中重复。因此,算法必须检测到这一点,并从偏好为3和4的数组中删除这些对象,因为2arr.filtero=> dupsMap.geto.id==o//如果该项是用作值的对象,则保留该项 常数arr\u p1f=过滤器arrrar\u p1 常数arr\u p2f=filter

我正在尝试按首选项删除四个数组之间的所有重复对象。所有数组都有唯一的元素,并且可能没有顺序。下面是一张试图解释问题的图片:

如您所见,如果数组具有较低的首选项,则元素将保留在其中。例如,id为6的对象在首选项为2、3和4的数组中重复。因此,算法必须检测到这一点,并从偏好为3和4的数组中删除这些对象,因为2<3<4

因此,如果输入数据为:

  arr_p1 = [{ id: "892d" }, {id: "kla8x" }, {id: "sys32" }]
  arr_p2 = [{id: "saa1" }, { id: "892d" }]
  arr_p3 = [{ id: "kla8x" }, {id: "saa1" }, {id: "pp182" }]
输出必须是:

  arr_p1 = [{ id: "892d" }, {id: "kla8x" }, {id: "sys32" }]
  arr_p2 = [{id: "saa1" }]
  arr_p3 = [{id: "pp182" }]
关于如何以良好的复杂性顺序解决这种情况,有什么想法吗

所有阵列的大小限制为40个对象

我唯一能想到的就是按标识符对每个数组中的所有对象进行排序。然后,获取一个对象的最低标识符,该标识符随每个列表的指针一起移动,从最低首选项1移动到最高首选项4,如果它在较高首选项列表中,则将其删除。。。但我需要在不改变元素顺序的情况下完成它


Pd:我使用的是JS和ES6。

将所有项目组合到一个数组中,然后使用array.reduceRight按相反顺序将它们缩减为一个映射。相反的顺序将导致第一个项目覆盖最后一个项目

现在,您可以使用映射过滤每个数组,并只保留映射上存在的项目

复杂性是ON1+N2+N3,其中Nx是该数组的长度

常量arr_p1=[{id:892d},{id:kla8x},{id:sys32}] const arr_p2=[{id:saa1},{id:892d}] 常量arr_p3=[{id:kla8x},{id:saa1},{id:pp182}] //创建一个包含所有项目的数组,并按相反顺序将其缩减为映射 常数dupsMap=[…arr_p1,…arr_p2,…arr_p3] //使用'id'作为键,使用对象作为值来创建映射 .reduceRightacc,o=>acc.seto.id,o,新地图 常量过滤器arr=arr=>arr.filtero=> dupsMap.geto.id==o//如果该项是用作值的对象,则保留该项 常数arr\u p1f=过滤器arrrar\u p1 常数arr\u p2f=filterrarr\u p2 常数arr\u p3f=过滤器arrar\u p3
log{arr_p1f,arr_p2f,arr_p3f}将所有项组合到一个数组中,然后使用array.reduceRight以相反的顺序将它们还原为映射。相反的顺序将导致第一个项目覆盖最后一个项目

现在,您可以使用映射过滤每个数组,并只保留映射上存在的项目

复杂性是ON1+N2+N3,其中Nx是该数组的长度

常量arr_p1=[{id:892d},{id:kla8x},{id:sys32}] const arr_p2=[{id:saa1},{id:892d}] 常量arr_p3=[{id:kla8x},{id:saa1},{id:pp182}] //创建一个包含所有项目的数组,并按相反顺序将其缩减为映射 常数dupsMap=[…arr_p1,…arr_p2,…arr_p3] //使用'id'作为键,使用对象作为值来创建映射 .reduceRightacc,o=>acc.seto.id,o,新地图 常量过滤器arr=arr=>arr.filtero=> dupsMap.geto.id==o//如果该项是用作值的对象,则保留该项 常数arr\u p1f=过滤器arrrar\u p1 常数arr\u p2f=filterrarr\u p2 常数arr\u p3f=过滤器arrar\u p3
log{arr_p1f,arr_p2f,arr_p3f}您可以生成一个首选项对象哈希映射,将id映射到首选项。从第三个数组运行到第一个数组,以便较低的顺序覆盖较高的顺序

然后,当您拥有首选项映射时,可以通过检查id的首选项是否与当前数组匹配来过滤所有数组

设arr_p1=[{id:892d},{id:kla8x},{id:sys32}]; 设arr_p2=[{id:saa1},{id:892d}]; 设arr_p3=[{id:kla8x},{id:saa1},{id:pp182}]; 设pref={}; arr_p3.forEache=>pref[e.id]=3; arr_p2.forEache=>pref[e.id]=2; arr_p1.forEache=>pref[e.id]=1; arr_p1=arr_p1.filtere=>pref[e.id]==1; arr_p2=arr_p2.filtere=>pref[e.id]==2; arr_p3=arr_p3.filtere=>pref[e.id]==3; console.logarr_p1; console.logarr_p2;
console.logarr_p3 您可以生成一个首选项对象哈希映射,将id映射到首选项。从第三个数组运行到第一个数组,以便较低的顺序覆盖较高的顺序

然后,当您拥有首选项映射时,可以通过检查id的首选项是否与当前数组匹配来过滤所有数组

设arr_p1=[{id:892d},{id:kla8x},{id:sys32}]; 设arr_p2=[{id:saa1},{id:892d}]; 设arr_p3=[{id:kla8x},{id:saa1},{id:pp182}]; 设pref={}; arr_p3.forEache=>pref[e.id]=3; arr_p2.forEache=>pref[e.id]=2; arr_p1.forEache=>pref[e.id]=1; arr_p1=arr_p1.filtere=>pref[e.id]==1; arr_p2=arr_p2.filtere=>pref[e.id]==2; arr_p3=arr_p3.filtere=>pref[e.id]==3; console.logarr_p1; console.logarr_p2;
console.logarr_p3 我有几个建议给你,而不是一个完整的答案,因为我假设这是一个家庭作业的问题

策略 构建一组已看到的项 检查每个新阵列,删除所有dupl 复制新数组中的条目

从最首选的阵列开始 这样,每当删除某个内容时,它都会从不太受欢迎的数组中删除

例如,在伪代码中

let elementsSeen = new Set(   most preferred array of elements   )

for array in listOfArraysInDecreasingOrderOfPreference {

  for element in array {
    if element is in elementsSeen, delete it from array
  }
  elementsSeen = union of elementsSeen and array
}
复杂性 每一项都要看。它必须与每一个其他项目进行比较,但其复杂性不一定很大,因为“Set”过程可以利用散列,即不必对每个传入对象与每个现有对象进行单独比较。几乎所有传入对象都有一个哈希表值,该值与现有对象的哈希表值不同,它很快,但代价是在哈希上花费一些时间和在表上花费一些内存。
在最坏的情况下,散列不再对您有帮助,而是在x M上,其中N是数组的数量,M是每个数组的大小。

我有一些提示,而不是完整的答案,因为我假设这是一个家庭作业问题

策略 构建一组已看到的项 对照此检查每个新数组,删除新数组中的任何重复项

从最首选的阵列开始 这样,每当删除某个内容时,它都会从不太受欢迎的数组中删除

例如,在伪代码中

let elementsSeen = new Set(   most preferred array of elements   )

for array in listOfArraysInDecreasingOrderOfPreference {

  for element in array {
    if element is in elementsSeen, delete it from array
  }
  elementsSeen = union of elementsSeen and array
}
复杂性 每一项都要看。它必须与每一个其他项目进行比较,但其复杂性不一定很大,因为“Set”过程可以利用散列,即不必对每个传入对象与每个现有对象进行单独比较。几乎所有传入对象都有一个哈希表值,该值与现有对象的哈希表值不同,它很快,但代价是在哈希上花费一些时间和在表上花费一些内存。
在最坏的情况下,散列不再对您有帮助,而是在x M上,其中N是数组的数量,M是每个数组的大小。

您的问题意味着您希望对原始数组进行变异

所以如果你仍然想变异数组,你可以

为每个级别创建一组ID。 将每个级别向后循环,如果在更高级别中有任何id,则从数组中删除。 这里还有一些优化,例如切片0,-1,这样我们就不需要为最后一个级别创建一个集合,就像之前检查的一样。在循环中,一旦知道要删除的项,使用一个中断,然后继续下一步。老实说,我不知道这有多复杂

例如

常数arr_p1= [{id:892d},{id:kla8x},{id:sys32}]; 常数arr_p2= [{id:saa1},{id:892d}]; 常数arr_p3= [{id:kla8x},{id:saa1},{id:pp182}]; 函数重复数据列表{ const hasList=alist.map m=>newsetm.slice0,-1.mapi=>i.id; 对于let l=alist.length-1;l>0;l-{ 对于let i=alist[l]。长度-1;i>=0;i-{ 对于设h=0;hconsole.logarr_p3 您的问题意味着您希望对原始数组进行变异

所以如果你仍然想变异数组,你可以

为每个级别创建一组ID。 将每个级别向后循环,如果在更高级别中有任何id,则从数组中删除。 这里还有一些优化,例如切片0,-1,这样我们就不需要为最后一个级别创建一个集合,就像之前检查的一样。在循环中,一旦知道要删除的项,使用一个中断,然后继续下一步。老实说,我不知道这有多复杂

例如

常数arr_p1= [{id:892d},{id:kla8x},{id:sys32}]; 常数arr_p2= [{id:saa1},{id:892d}]; 常数arr_p3= [{id:kla8x},{id:saa1},{id:pp182}]; 函数重复数据列表{ const hasList=alist.map m=>newsetm.slice0,-1.mapi=>i.id; 对于let l=alist.length-1;l>0;l-{ 对于let i=alist[l]。长度-1;i>=0;i-{ 对于设h=0;hconsole.logarr_p3;数组数量是否固定?对象中的数据是否多于此id?是,数组数量固定,否,唯一数据是id。数组数量是否固定?对象中的数据是否多于此id?是,数组数量固定,否,唯一数据是id。