使用递归函数删除所有重复的数组元素

时间:2014-10-25 14:18:30

标签: javascript

我想得到的就像clean([3,2,3,2,5,1]) == [5,1],出于学习目的,我想使用递归函数和vanilla javascript来做。我写的函数如下:

r=[];
var clean = function(array){
    var s1=array.slice(0);
    var s2=array.slice(0);
    if(s2[0] !== undefined) {
        r.push(s2.shift());
        for (i=0,flag=false;i<s2.length;i++){
            if (r[r.length-1] == s2[i]){
                s1[i+1]=undefined;
                flag=true;
            }
        }
        if (flag==true){
            r.pop();
            s1.shift();
            for (j=0;j<s1.length;j++){
                if (s1[j] == undefined) {s1.splice(j,1);j--};
            }
        } 
        else{
            s1.shift();
        }
    }
    if (s2.length !== 0) clean(s1);
    return;
}

看起来很有效,但有些事情让我感觉不舒服:

首先,我对编程非常陌生,当我编写javascript函数时,我总觉得需要在函数外部定义一个变量来存储结果,在这种情况下为r,我知道这是一个非常糟糕的做法,我应该在函数内部定义一个变量并返回它。但是我花了6个小时写上面的代码(不要嘲笑我),现在我的大脑完全让我失望了,我无法想到将这个变量带入函数的方法。任何提示都非常感谢;

其次,当我遍历一个数组并对其进行修改时,其长度会随时变化,使得循环不可靠,我不得不将数组复制到2个不同的变量(s1,s2)以避免循环问题。这很尴尬。后来我想到我可以在数组长度发生变化的同时修改循环索引(正如你在j循环中看到的那样),但这是一个好习惯吗?以下改进的功能似乎也有效:

var ccc = function(array){
    var s1=array.slice(0);
    if(s1[0] !== undefined) {
        r.push(s1.shift());
        for (i=0,flag=false;i<s1.length;i++){
            if (r[r.length-1] == s1[i]){
                s1.splice(i,1);
                i--;
                flag=true;
            }
        }
        if (flag==true){
            r.pop();
        }
        if (s1.length !== 0) ccc(s1);
    }
    return;
}

此外,我知道jQuery可能有一个实现这个功能,但如果不允许框架,最好的方法是什么(递归与否)?我简要搜索一下stackoverflow,但没有找到确切的答案。

1 个答案:

答案 0 :(得分:1)

在我看来,这可以大大简化。你的代码有标志,还有很多东西。

相反,JavaScript数组已经提供了转换方法 - 一种用于从您不想要的数组中删除元素并返回仅包含您执行的元素的新数组的方法是.filter

var clean = myArr.filter(function(el, i, arr){ 
    // filter the array
    // if we return true from here - the element will stay, otherwise it won't
    return (arr.indexOf(el) === i) && (arr.lastIndexOf(el) === i);
});

基本上,我们的代码是说&#34;元素的第一个和最后一个索引与此一个相同&#34; - 意味着数组中只有一个元素。这不是最快的方式,但它非常干净,无论如何,性能对于小型阵列都不重要。你可以把它放在一个函数中,当然:

&#13;
&#13;
    function clean(arr) {
      return arr.filter(function(el, i) {
        return (arr.indexOf(el) === i) && (arr.lastIndexOf(el) === i);
      });
    }
    alert(clean([3, 2, 3, 2, 5, 1]));
&#13;
&#13;
&#13;

我相信它比你开始时更短,更清晰,更易读。在ES6(规范JavaScript的下一版本基础上)并使其慢一点 - 这变得更加清晰:

let clean = (arr) => arr.filter((el, i) => arr.indexOf(el) === arr.lastIndexOf(el));
alert(clean([3, 2, 3, 2, 5, 1]));