Javascript 从JS数组中删除重复值
我有一个非常简单的JavaScript数组,它可能包含也可能不包含重复项Javascript 从JS数组中删除重复值,javascript,arrays,duplicates,unique,Javascript,Arrays,Duplicates,Unique,我有一个非常简单的JavaScript数组,它可能包含也可能不包含重复项 var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; 我需要删除重复项并将唯一值放入新数组中 我可以指出我尝试过的所有代码,但我认为这是无用的,因为它们不起作用。我也接受jQuery解决方案 类似问题: 香草JS:使用类似集合的对象删除重复项 var x=[1,2,3,3,2,1]; x.unique() //[1,2,3] var a
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放入新数组中
我可以指出我尝试过的所有代码,但我认为这是无用的,因为它们不起作用。我也接受jQuery解决方案
类似问题:
var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]
var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });
您始终可以尝试将其放入对象中,然后遍历其键:
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;
}
用法示例:
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"]
TL;博士
使用构造函数和
“聪明”但天真的方式 基本上,我们迭代数组,对于每个元素,检查数组中该元素的第一个位置是否等于当前位置。显然,对于重复元素,这两个位置是不同的 使用过滤器回调的第3个(“this array”)参数,我们可以避免数组变量关闭:
uniqueArray = a.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
虽然简洁,但该算法对于大型阵列(二次时间)不是特别有效
哈希表的解救
通常是这样做的。其思想是将每个元素放在哈希表中,然后立即检查其存在性。这给了我们线性时间,但至少有两个缺点:
- 由于哈希键在JavaScript中只能是字符串或符号,因此此代码不区分数字和“数字字符串”。也就是说,
将只返回uniq([1,“1”])
[1]
- 出于同样的原因,所有对象都将被视为相等:
将只返回uniq([{foo:1},{foo:2}])
[{foo:1}]
function uniq(a) {
var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];
return a.filter(function(item) {
var type = typeof item;
if(type in prims)
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
else
return objs.indexOf(item) >= 0 ? false : objs.push(item);
});
}
排序| uniq
另一个选项是先对数组排序,然后删除与前一个元素相等的每个元素:
function uniq(a) {
return a.sort().filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
});
}
同样,这不适用于对象(因为对于排序
,所有对象都是相等的)。此外,我们悄悄地更改原始阵列作为副作用-不好!但是,如果您的输入已经排序,这就是方法(只需从上面删除sort
)
独一无二的。。。
有时,我们希望根据一些标准(而不仅仅是相等)对列表进行唯一化,例如,筛选出不同但共享某些属性的对象。这可以通过传递回调优雅地完成。此“键”回调应用于每个元素,并删除具有相等“键”的元素。由于键
预计将返回原语,因此哈希表在这里可以正常工作:
function uniqBy(a, key) {
var seen = {};
return a.filter(function(item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
})
}
一个特别有用的key()
是JSON.stringify
,它将删除物理上不同但“外观”相同的对象:
a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]
如果键
不是原语,则必须使用线性搜索:
function uniqBy(a, key) {
var index = [];
return a.filter(function (item) {
var k = key(item);
return index.indexOf(k) >= 0 ? false : index.push(k);
});
}
在ES6中,您可以使用集合
:
function uniqBy(a, key) {
let seen = new Set();
return a.filter(item => {
let k = key(item);
return seen.has(k) ? false : seen.add(k);
});
}
或地图
:
function uniqBy(a, key) {
return [
...new Map(
a.map(x => [key(x), x])
).values()
]
}
这两种方法也适用于非基本键
第一个还是最后一个?
通过键删除对象时,可能希望保持第一个或最后一个“相等”对象
使用上面的设置
变量保留第一个,使用映射
保留最后一个:
函数uniqByKeepFirst(a,键){
let seen=新集合();
返回a.filter(项=>{
设k=键(项);
返回seen.has(k)?false:seen.add(k);
});
}
函数uniqByKeepLast(a,键){
返回[
…新地图(
a、 映射(x=>[键(x),x])
).values()
]
}
//
数据=[
{a:1,u:1},
{a:2,u:2},
{a:3,u:3},
{a:4,u:1},
{a:5,u:2},
{a:6,u:3},
];
log(uniqByKeepFirst(data,it=>it.u))
log(uniqByKeepLast(data,it=>it.u))
使用jQuery快速且不干净:
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});
使用
它是一个库,包含许多用于操纵数组的函数
这是与jQuery的tux和Backbone.js搭配的纽带
吊带
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
alert(_.uniq(names, false));
\uuq.uniq(数组,[isSorted],[iterator])
别名:唯一使用===来测试对象,生成数组的重复免费版本 平等。如果您事先知道数组已排序,则传递 对于为true,排序后的将运行更快的算法。如果你想 基于转换计算唯一项,传递一个迭代器 功能
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
alert(_.uniq(names, false));
注:(竞争对手)也提供了类似的实现。以下内容比列出的jQuery方法快80%以上(参见下面的测试)。 这是几年前一个类似问题的答案。如果我遇到最初提出这个建议的人,我会贴信用卡。 纯JS
var-temp={};
对于(var i=0;i
我的测试用例比较:
最重要的答案的复杂性为
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;
});
}
这适用于字符串、数字和日期。如果数组包含对象,则上述解决方案将不起作用,因为当强制为字符串时,它们的值都将为“[object object]”
(或类似值),而这不适合用作查找值。您可以通过在对象本身上设置标志来获得对象的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 getDistinctArray(arr) {
var dups = {};
return arr.filter(function(el) {
var hash = el.valueOf();
var isDup = dups[hash];
dups[hash] = true;
return !isDup;
});
}
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;
}
function getDistinctArray(arr) {
return [...new Set(arr)];
}
arr = arr.filter (function (value, index, array) {
return array.indexOf (value) == index;
});
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniq = names.reduce(function(a,b){
if (a.indexOf(b) < 0 ) a.push(b);
return a;
},[]);
console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
// one liner
return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);
var uniq = names.slice() // slice makes copy of array before sorting it
.sort(function(a,b){
return a > b;
})
.reduce(function(a,b){
if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop())
return a;
},[]); // this empty array becomes the starting value for a
// one liner
return names.slice().sort(function(a,b){return a > b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);
var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']
var uniq = names
.map((name) => {
return {count: 1, name: name}
})
.reduce((a, b) => {
a[b.name] = (a[b.name] || 0) + b.count
return a
}, {})
var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b])
console.log(sorted)
function contains(array, obj) {
for (var i = 0; i < array.length; i++) {
if (isEqual(array[i], obj)) return true;
}
return false;
}
//comparator
function isEqual(obj1, obj2) {
if (obj1.name == obj2.name) return true;
return false;
}
function removeDuplicates(ary) {
var arr = [];
return ary.filter(function(x) {
return !contains(arr, x) && arr.push(x);
});
}
$(document).ready(function() {
var arr1=["dog","dog","fish","cat","cat","fish","apple","orange"]
var arr2=["cat","fish","mango","apple"]
var uniquevalue=[];
var seconduniquevalue=[];
var finalarray=[];
$.each(arr1,function(key,value){
if($.inArray (value,uniquevalue) === -1)
{
uniquevalue.push(value)
}
});
$.each(arr2,function(key,value){
if($.inArray (value,seconduniquevalue) === -1)
{
seconduniquevalue.push(value)
}
});
$.each(uniquevalue,function(ikey,ivalue){
$.each(seconduniquevalue,function(ukey,uvalue){
if( ivalue == uvalue)
{
finalarray.push(ivalue);
}
});
});
alert(finalarray);
});
var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"];
var uniqueNames = [];
for(var i in names){
if(uniqueNames.indexOf(names[i]) === -1){
uniqueNames.push(names[i]);
}
}
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
unique = [...new Set(names)];
var uniqueArray = duplicateArray.filter(function(elem, pos) {
return duplicateArray.indexOf(elem) == pos;
});
Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Yes) 1.5 (1.8) 9 (Yes) (Yes)
var duplicates = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl","Mike","Mike","Nancy","Carl"];
var unique = duplicates.filter(function(elem, pos) {
return duplicates.indexOf(elem) == pos;
});
alert(unique);
d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]
vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
vals.filter(function(v, i, a){ return i == a.indexOf(v) })
Array.from(new Set(vals))
[...new Set(vals)]
var uniqueArray = dupeArray.filter(function(item, i, self){
return self.lastIndexOf(item) == i;
});
var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");
peoplenames = unique(peoplenames);
alert(peoplenames);
function unique(array){
var len = array.length;
for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++)
if(array[j] == array[i]){
array.splice(j,1);
j--;
len--;
}
return array;
}
//*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl", "Mike", "Nancy"]
var noDupe = Array.from(new Set(names))
let a = [11,22,11,22];
let b = []
b = [ ...new Set(a) ];
// b = [11, 22]
b = Array.from( new Set(a))
// b = [11, 22]
b = a.filter((val,i)=>{
return a.indexOf(val)==i
})
// b = [11, 22]
Array.prototype.unique = function() {
var a = [];
for (i = 0; i < this.length; i++) {
var current = this[i];
if (a.indexOf(current) < 0) a.push(current);
}
return a;
}
Array.prototype.unique = function() {
return Array.from(new Set(this));
}
var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]
var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });
a.filter((v,i) => a.indexOf(v) == i)
function removeDuplicates(arr){
o={}
arr.forEach(function(e){
o[e]=true
})
return Object.keys(o)
}
let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);
for (i=0; i<originalArray.length; i++) {
if (!newArray.includes(originalArray[i])) {
newArray.push(originalArray[i]);
}
}