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

Using recursive function to remove all duplicated array elements

本文关键字:数组元素 递归函数 删除      更新时间:2023-09-26

我想要得到的是像clean([3,2,3,2,5,1]) == [5,1]一样的东西,出于学习目的,我只想使用递归函数和普通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个小时写了上面的代码(不要嘲笑我),现在我的大脑完全辜负了我,我想不出把这个变量代入函数的方法。任何提示都将不胜感激;

其次,当我循环遍历一个数组并修改它时,它的长度会不断变化,使循环变得不可靠,我不得不将数组复制到两个不同的变量(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附近找了一下,但没有找到确切的答案。

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

相反,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);
});

基本上,我们的代码是说"元素的第一个和最后一个索引与这个索引相同"——这意味着数组中只有一个元素。这不是最快的方法,但它非常干净,而且性能对小型阵列来说并不重要。当然,你可以把它放在一个函数中:

    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]));

我相信它比你刚开始的要短得多,更干净,可读性也更强。在ES6中(JavaScript规范的下一个版本基于此),并使其速度慢一点——这变得更加干净:

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