Javascript 消除大量阵列重复数据的有效方法
我有一个非常大的数组(大约960799个条目,或者可能更大)。我需要将其处理为一个新阵列,以便:Javascript 消除大量阵列重复数据的有效方法,javascript,arrays,Javascript,Arrays,我有一个非常大的数组(大约960799个条目,或者可能更大)。我需要将其处理为一个新阵列,以便: 每个子数组不包含重复项 主数组不包含重复的子数组 问题是,“重复子数组”必须包含具有不同顺序的相同值的数组。换句话说,如果我有这些子数组: [[1,2,3],[1,2,3],[3,1,2]] 它们都被认为是重复的,只保留一个(其中任何一个都不重要;我只保留了第一个;如果所选子数组的顺序实际上不匹配也可以,即如果子数组中元素的顺序在处理过程中发生变化) 我尝试的解决方案是,根据子数组的重复数据消除、排
[[1,2,3],[1,2,3],[3,1,2]]
它们都被认为是重复的,只保留一个(其中任何一个都不重要;我只保留了第一个;如果所选子数组的顺序实际上不匹配也可以,即如果子数组中元素的顺序在处理过程中发生变化)
我尝试的解决方案是,根据子数组的重复数据消除、排序和使用分隔符连接,将所有子数组映射为字符串。然后我对最后一个数组进行重复数据消除,然后将它们映射回具有拆分的数组。这是可行的,但过程非常缓慢。单次扫描需要30秒以上的时间,而且由于我最终处理的阵列可能会成倍增大,这是不可接受的。我需要一个更有效的算法
下面是我现在使用的代码,速度很慢(ret
是输入数组):
谁能帮我更有效地得到同样的结果?谢谢
编辑
更详细地说,我通过计算一些字符串输入的幂集来获得这些大量的输入数组。这就是代码;如果有可能首先阻止它产生重复条目,我认为这也会很好地工作:
// Calculate the Cartesian product of set s
function cart(s) {
return s.reduce((acc, val) => {
return acc.map((x, i) => {
return val.map(y => {
return x.concat([y]);
});
}).flat();
}, [[]]);
}
// Use the Cartesian product to calculate the power set of set s
function pset(s) {
let ret = [];
for (let i = 0; i < s.length; ++i) {
const temp = [];
for (let j = 0; j <= i; ++j) {
temp.push([].concat(s));
}
ret = ret.concat(cart(temp));
}
return ret;
}
//计算集合s的笛卡尔积
功能车{
返回s.reduce((acc,val)=>{
返回acc.map((x,i)=>{
返回val.map(y=>{
返回x.concat([y]);
});
}).flat();
}, [[]]);
}
//使用笛卡尔积计算集合s的幂集
功能pset(s){
设ret=[];
对于(设i=0;i 对于(假设j=0;j),您可以生成无重复项的功率集
函数pset(数组){
功能iter(索引、温度){
如果(索引>=array.length){
温度长度和结果推送(温度);
返回;
}
国际热核实验堆(指数+1,温度混凝土(阵列[指数]);
iter(指数+1,温度);
}
var结果=[];
iter(0,[]);
返回结果;
}
console.log(pset(['a','b','c']);
.as console wrapper{max height:100%!important;top:0;}
考虑到我无法使用真实数据执行基准测试,我无法验证这种方法对您的用例来说快了多少,但是通过对
循环使用基本,并尽可能方便地避免使用函数代码,我得出以下结论:
const ret=[[1,2,3]、[1,2,3]、[3,1,2]、[1,4,5]、[4,1,5];
函数升序(a,b){
//适用于字符串和数字
返回-(ab);
}
功能提升2D(a,b){
常数长度=a.长度;
常量长度=b.长度;
常量长度=数学最小值(长度、混合度);
for(设i=0;i console.log(output);
EDIT:Nevermind,我的实现没有基准。速度较慢。这是由于JSON.parse
、JSON.stringify
的底层实现,以及数组#排序的默认算法
由于您正在寻找最先进的性能,因此很难获得一个优雅的解决方案。如果您使用object.create(null)
实例化一个对象,则可以将O(1)的开销降至最低插入。它创建一个没有原型的POJO。您也不需要在对象的in
循环中签入,因为没有原型可搜索
const ret=[[],[1,2,3],[3,1,2],[1,4,5],[4,1,5];
const hashMap=Object.create(null)
函数createUniqArraysOfPrimitiveArrays(ret){
for(设i=0;i console.log(createUniqArraysOfPrimitiveArrays(ret))
我知道你的问题是关于重复数据消除的,但是你的阵列和子阵列首先是如何生成的?在效率方面,如果可能的话,最好是在一开始就不生成重复的阵列和子阵列。看看这个答案,了解一些想法@PatrickRoberts,它们基本上被计算为一个值的输入数组。基本上,我有一个计算数组笛卡尔积的函数。我在越来越长的相同输入数组集上运行该函数,重复1到N次(N=输入的长度)并将结果连接在一起。这确实会产生一个幂集,但现在我需要消除该结果的重复,因为较小迭代的乘积与较大迭代的乘积重叠。我将看看是否可以修改幂集代码,以首先防止重复。@PatrickRoberts我已将幂集计算代码添加到OP.I中我试图修改它以防止生成重复项,结果却从最终输出中删除了合法的唯一值;我不同意
// Calculate the Cartesian product of set s
function cart(s) {
return s.reduce((acc, val) => {
return acc.map((x, i) => {
return val.map(y => {
return x.concat([y]);
});
}).flat();
}, [[]]);
}
// Use the Cartesian product to calculate the power set of set s
function pset(s) {
let ret = [];
for (let i = 0; i < s.length; ++i) {
const temp = [];
for (let j = 0; j <= i; ++j) {
temp.push([].concat(s));
}
ret = ret.concat(cart(temp));
}
return ret;
}