JavaScript-消除重复的算法效率

JavaScript-消除重复的算法效率,javascript,algorithm,duplicate-removal,Javascript,Algorithm,Duplicate Removal,我读了很多关于这个主题的书,看到了很多不同的算法。我偶然发现了另一个解决方案,与其他算法相比,我很难理解它的效率,因为它使用一个简单的临时对象来保存数组的现有元素。与使用复杂排序方法和比较的“老派”方法相比,这是有效的解决方案吗 function removeDup(arr){ var element, existObj= {}, finalArr = []; for(var i=0;i<a

我读了很多关于这个主题的书,看到了很多不同的算法。我偶然发现了另一个解决方案,与其他算法相比,我很难理解它的效率,因为它使用一个简单的临时对象来保存数组的现有元素。与使用复杂排序方法和比较的“老派”方法相比,这是有效的解决方案吗

 function removeDup(arr){
        var element,
                existObj= {},
                finalArr = [];

        for(var i=0;i<arr.length;i++){
            element = arr[i];
            if(!existObj[element]){
                finalArr.push(element);
                existObj[element] = true;
            }
        }
        return finalArr;
    }
    //console.log(removeDup([2,2,2,2,4534,5,7,3]));
    console.log(removeDup(["mike","john","alex","mike","john"]));
功能移除(arr){
var元素,
existObj={},
finalArr=[];

对于(var i=0;i您将通过使用最合适的数据结构获得最佳性能

这是一个您首先应该使用的集合:这样您甚至不必做任何事情来删除DUP,添加DUP时它们将被忽略。
我只是做了一个简单的测试,一套设备的性能要快六到十倍(!!)

结果示例:

"overhead is : 0.015700000221841037"
"Built unic numbers with a lookup object in : 6.237600000167731"
"Built unic numbers with a Set in : 0.7921500000520609"
以下是两种算法的n=0到50.000的曲线。
我们看到,hashmap的行为确实与O(1)非常相似,但当n增加时,其传播更大。
集合几乎是完全线性的

图纸jsbin(耐心等待!):

代码:

// noprotect
// build a test set
var numbers = [];
var cnt = 10000; 
for (var i=0; i<cnt; i++ ) numbers.push(Math.floor(Math.random*1000));

// build unic values using lookup object
function buildWithObject() {
  var existing= {};
  var unicNumbers = [];
  for (var i=0; i<cnt; i++) {
    var num = numbers[i];
    if (!existing[num]) {
      unicNumbers.push(num);
      existing[num]=true;
    }
  }
}

// build unic values using a Set
function buildWithSet() {
    var unicNumbersSet = new Set();
    for (var i=0; i<cnt; i++) {
         var num = numbers[i];
         unicNumbersSet.add(num);
    }  
}

function iterate() {
    for (var i=0; i<cnt; i++) {
         var num = numbers[i];
    }    
}

// warming up functions
for (var i=0; i<30; i++) { buildWithObject(); buildWithSet() ;  iterate(); }

// --------  Measures  --------------------
var measureRepeat = 20;
var m;

var s,e;
// ----------------------------
m=measureRepeat;
s=window.performance.now();
while (m--) iterate();
e=window.performance.now();

console.log('overhead is : ' + (e-s)/measureRepeat);

// ----------------------------
m=measureRepeat;
s=window.performance.now();
while (m--) buildWithObject();
e=window.performance.now();

console.log('Built unic numbers with a lookup object in : ' + (e-s)/measureRepeat);

// ----------------------------
m=measureRepeat;
s=window.performance.now();
while (m--) buildWithSet();
e=window.performance.now();
console.log('Built unic numbers with a Set in : ' + (e-s)/measureRepeat);
//无保护
//构建测试集
var数=[];
var-cnt=10000;

对于(var i=0;我认为
existObj
是一个散列映射-具有接近
O(1)
的分配和访问性能。使用@Bergi更容易:你是对的,因为O(1)+常量==0(1),我们没有用于查找的“接近”O(1),而是精确的O(1)。所以这个算法是O(n).现在,如我的回答所示,通过使用最合适的本机对象,我们可以将此O(n)的“k”提高6-10倍。@GameAlchemist:我不是说常数。在哈希映射中分配和访问元素将始终取决于键的
(k)
大小(例如属性字符串的长度),
(v)
存储值的大小,以及地图中项目的数量-只是具有非常好的复杂性。(免责声明:
v
对于像这里这样的布尔值或对象指针是常量;
k
可以通过一个不访问所有字节的惰性散列函数来减少;
n
如果键空间是有限的,则可能会受到限制)@Bergi:我想检查O(1)是否足够好,所以我做了一个绘图(见我的答案)。确实是O(1)这是一个很好的近似值,即使差价随着n的增加而增加。嗯,是的,我会担心
Set
@Bergi的兼容性。是的,这可能是一个问题,取决于你的目标。我更新了兼容性表的摘要。(但在几个月内,一切都会好起来,因为和谐(不知何故)受到每个人的欢迎)。谢谢你的回答。总之,假设使用对象作为查找映射是正确的,并且复杂度是O(N)。但是,使用集合要快得多,但复杂度仍然是O(N)?是的,正如你所知道的O(N)表示k*n+ctte,一个集合的k常数大约小10倍。虽然这段代码可以提供问题的解决方案,但最好添加上下文,说明它为什么/如何工作。这可以帮助未来用户学习,并将知识应用到他们自己的代码中。当c对其进行了解释。
let existing = {};
let unicNumbers = [];   
arr.forEach((item) => {
        if (!existing[item.id]) {
            unicNumbers.push(item);
            existing[item.id] = true;
        }
    })