从数组arr中去掉repeatArr,我能想到的最好的方法是递归,有没有比较简洁的方法?

arr和repeatArr都不会出现重复项,而且repeatArr一定是类似数学里的集合,repeatArr是属于arr的`
var arr = [1, 2, 3, 4, 5];

var repeatArr = [1, 3];
function distinct() {
    for (var i = 0; i < arr.length; i++) {
        for (var j = 0; j < repeatArr.length; j++) {
            if (arr[i] == repeatArr[j]) {
                arr.splice(i, 1);
                distinct()
                return false;
            }
        }
    }
}
distinct();
console.log(arr)
阅读 3.9k
7 个回答
  1. 先把“去重”的概念说清楚吧。
  2. 去重这种,O(n) 的时间复杂度就够了。

arr.filter(item => !repeatArr .includes(item))

先说一下原来的代码。
做一个双循环也并不需要用到递归,找到重复项原地踏步就行!
直接操作外部变量也不是一个好的选择!

if (arr[i] == repeatArr[j]) {
    arr.splice(i, 1);
    i--
    break;
}

另外,
去重最常用的像上面说的,使用哈希,就不累赘了哈!

其实你可以从几个方面考虑一下上面几种答案。
1、是否纯函数或者说是否直接修改外部变量
2、性能、复杂度
3、代码可读性(这个不说了,大家都有自己的见解)

    arr.filter(item => !repeatArr.includes(item))
    
    function fp(origin, repeat) {
      return origin.filter(item => !repeat.includes(item))
    }

第一种偏函数式,不影响外部,可以很轻松封装成函数,也方便复用!
复杂度也是O(n^2),上用大白话说,其实也就是双循环。

    var arr = [1, 2, 3, 4, 5];
    var repeatArr = [1, 3];
    var map = {};
    $.map(repeatArr, function(v){map[v] = true})
    arr = $.map(arr, function(v){if(!map[v]){return v}})
    
    function hashMapUnique(origin, repeat) {
      let map = {};
      repeat.map(item => map[item] = true)
      return origin.filter(item => !map[item])
    }

第二种用也比较容易封装成函数
哈希在数据访问的时候比遍历要快,在处理的量大的情况下,性能优于第一种方法

刚刚还看到了第三种使用正则的。
还挺复杂的,最后数据类型也发生变化了。
没有尝试哈!

最后说一下你改以后的方法哈

for (var i = 0; i < repeatArr.length;i++) {
    var index = arr.indexOf(repeatArr[i]);
    arr.splice(index, 1);
}

就像yszou说的你的复杂度上没有优势!
而且使用了splice方法,直接修改了原始数组不说,且这个方法本身就比较消耗性能的。
用大白话说,splice在删除那一项以后,得把该项以后的每一项都前移一位!
可读性上面我就不评论了哈·~~~

arr.filter((val,key,arr) => arr.indexOf(val) === key))

demo:链接描述

let arr = [1, 2, 3, 4, 5];
let repeatArr = [1, 3];
let s = String.fromCharCode(2);
let reg = new RegExp('(' + s + repeatArr.join(s + ')|(' + s) + s + ')', 'gi');
let str = s + arr.join(s) + s;
let result = str.replace(reg, s);
result = result.substring(1, result.length - 1).split(s);
alert(result);

这种要考虑的很多 比如arr是否允许重复元素能否先优化arr数组 如果都是number 在数据量大的时候是可以先进行排序的
repeatArr一定是不能存在重复元素的
然后不要修改元素组 而是创建新的数组 这样一次就可以筛选出
而不是distinct那样 会导致多次遍历了起始已遍历的数据

结合各位的意见,我用一个循环解决了。麻烦各位帮忙看看。

for (var i = 0; i < repeatArr.length;i++) {
    var index = arr.indexOf(repeatArr[i]);
    arr.splice(index, 1);
}
推荐问题