我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

我需要删除重复项并将唯一值放入新数组。

我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。

类似的问题:

获取数组中的所有非唯一值(即:重复/多次出现)


当前回答

var duplicates = function(arr){
     var sorted = arr.sort();
   var dup = [];
   for(var i=0; i<sorted.length; i++){
        var rest  = sorted.slice(i+1); //slice the rest of array
       if(rest.indexOf(sorted[i]) > -1){//do indexOf
            if(dup.indexOf(sorted[i]) == -1)    
         dup.push(sorted[i]);//store it in another arr
      }
   }
   console.log(dup);
}

duplicates(["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]);

其他回答

通用功能方法

以下是ES2015的通用和严格功能方法:

//小型、可重复使用的辅助功能常量应用=f=>a=>f(a);常量flip=f=>b=>a=>f(a)(b);常量未修正=f=>(a,b)=>f(a)(b);常量push=x=>xs=>(xs.push(x),xs);常量foldl=f=>acc=>xs=>xs.reduce(uncurry(f),acc);常量some=f=>xs=>xs.some(apply(f));//实际的重复数据消除功能常量uniqueBy=f=>foldl(acc=>x=>一些(f(x))(acc)? 应收账款:推(x)(acc)) ([]);//比较器常量eq=y=>x=>x===y;//字符串相等不区分大小写:D常量seqCI=y=>x=>x.toLowerCase()===y.toLowerCase();//模拟数据常量xs=[1,2,3,1,2,3,4];常量ys=[“a”、“b”、“c”、“a”、“b”、“c”、“D”];console.log(uniqueBy(eq)(xs));console.log(uniqueBy(seqCI)(ys));

我们可以很容易地从unqiueBy中派生出唯一的,或者使用Sets更快地实现:

const unqiue = uniqueBy(eq);

// const unique = xs => Array.from(new Set(xs));

此方法的优点:

使用单独比较器函数的通用解决方案声明性和简洁的实现其他小型通用函数的重用

性能注意事项

uniqueBy不如具有循环的命令式实现快,但由于它的泛型性,它更具表现力。

如果您确定uniqueBy是应用程序中具体性能损失的原因,请用优化的代码替换它。也就是说,首先以功能性、声明性的方式编写代码。之后,如果您遇到性能问题,请尝试在导致问题的位置优化代码。

内存消耗和垃圾收集

uniqueBy利用隐藏在其体内的突变(push(x)(acc))。它重用累加器,而不是在每次迭代后丢弃它。这减少了内存消耗和GC压力。由于这种副作用被包装在函数内部,所以外部的一切都保持纯净。

var uniqueCompnies = function(companyArray) {
    var arrayUniqueCompnies = [],
        found, x, y;

    for (x = 0; x < companyArray.length; x++) {
        found = undefined;
        for (y = 0; y < arrayUniqueCompnies.length; y++) {
            if (companyArray[x] === arrayUniqueCompnies[y]) {
                found = true;
                break;
            }
        }

        if ( ! found) {
            arrayUniqueCompnies.push(companyArray[x]);
        }
    }

    return arrayUniqueCompnies;
}

var arr = [
    "Adobe Systems Incorporated",
    "IBX",
    "IBX",
    "BlackRock, Inc.",
    "BlackRock, Inc.",
];

像这样使用Array.filter()

var actualArr=[苹果',苹果',香蕉',芒果',草莓',香蕉];console.log('实际数组:'+actualArr);var filteredArr=actualArr.filter(函数(项,索引){if(actualArr.indexOf(item)==索引)退货项目;});console.log('FilteredArray:'+filtedArr);

这可以在ES6中缩短到

actualArr.filter((item,index,self) => self.indexOf(item)==index);

下面是Array.filter()的详细解释

顶级答案的复杂度为O(n²),但这可以通过使用对象作为哈希来实现,只需O(n):

function getDistinctArray(arr) {
    var dups = {};
    return arr.filter(function(el) {
        var hash = el.valueOf();
        var isDup = dups[hash];
        dups[hash] = true;
        return !isDup;
    });
}

这将适用于字符串、数字和日期。如果您的数组包含对象,则上述解决方案将不起作用,因为当强制为字符串时,它们都将具有“[objectObject]”(或类似的值),这不适合作为查找值。通过在对象本身上设置标志,可以获得对象的O(n)实现:

function getDistinctObjArray(arr) {
    var distinctArr = arr.filter(function(el) {
        var isDup = el.inArray;
        el.inArray = true;
        return !isDup;
    });
    distinctArr.forEach(function(el) {
        delete el.inArray;
    });
    return distinctArr;
}

2019年编辑:JavaScript的现代版本使这个问题更容易解决。无论数组中是否包含对象、字符串、数字或任何其他类型,都可以使用Set。

function getDistinctArray(arr) {
    return [...new Set(arr)];
}

实现如此简单,不再需要定义函数。

使用本机javascript函数从数组中删除重复项的最简洁方法是使用以下序列:

vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])

在reduce函数中不需要slice或indexOf,就像我在其他示例中看到的那样!将其与过滤器功能一起使用是有意义的,尽管:

vals.filter(function(v, i, a){ return i == a.indexOf(v) })

ES6(2015)的另一种方法是:

Array.from(new Set(vals))

或者甚至使用扩展运算符:

[...new Set(vals)]

干杯