我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放入新数组。
我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放入新数组。
我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
当前回答
通用功能方法
以下是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压力。由于这种副作用被包装在函数内部,所以外部的一切都保持纯净。
其他回答
这可能是从阵列中永久删除重复项的最快方法之一比这里的大多数功能快10倍。&狩猎速度快78倍
function toUnique(a,b,c){ //array,placeholder,placeholder
b=a.length;while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
测试:http://jsperf.com/wgu演示:http://jsfiddle.net/46S7g/更多信息:https://stackoverflow.com/a/25082874/2450730
如果你看不懂上面的代码,请看一本javascript书,或者这里有一些关于较短代码的解释。https://stackoverflow.com/a/21353032/2450730
VanillaJS:使用像Set这样的Object删除重复项
您可以始终尝试将其放入对象中,然后遍历其关键点:
function remove_duplicates(arr) {
var obj = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
for (var key in obj) {
ret_arr.push(key);
}
return ret_arr;
}
Vanilla JS:通过跟踪已经看到的值来删除重复项(订单安全)
或者,对于订单安全版本,使用一个对象来存储所有以前看到的值,并在添加到数组之前检查值。
function remove_duplicates_safe(arr) {
var seen = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
if (!(arr[i] in seen)) {
ret_arr.push(arr[i]);
seen[arr[i]] = true;
}
}
return ret_arr;
}
ECMAScript 6:使用新的Set数据结构(顺序安全)
ECMAScript 6添加了新的Set Data Structure,它允许您存储任何类型的值。Set.values按插入顺序返回元素。
function remove_duplicates_es6(arr) {
let s = new Set(arr);
let it = s.values();
return Array.from(it);
}
示例用法:
a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
b = remove_duplicates(a);
// b:
// ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]
c = remove_duplicates_safe(a);
// c:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
d = remove_duplicates_es6(a);
// d:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
如果你在使用
D3.js
你可以的
d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]
https://github.com/mbostock/d3/wiki/Arrays#set_values
顶级答案的复杂度为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)];
}
实现如此简单,不再需要定义函数。
function removeDuplicates(inputArray) {
var outputArray=new Array();
if(inputArray.length>0){
jQuery.each(inputArray, function(index, value) {
if(jQuery.inArray(value, outputArray) == -1){
outputArray.push(value);
}
});
}
return outputArray;
}