所以为了帮助我学习,有人可以帮我确定原型脚本出了什么问题吗?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
filter
方法来按以下方式获取一个包含唯一值的数组:
function onlyUnique(value, index, array) {
return array.indexOf(value) === index;
}
// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter(onlyUnique);
console.log(unique); // ['a', 1, 2, '1']
本地方法filter
将循环遍历数组,并仅保留通过给定回调函数onlyUnique
的条目。
onlyUnique
检查给定值是否是第一次出现。如果不是,则必须是重复项,将不会被复制。
此解决方案无需任何额外的库,如jQuery或prototype.js。
它也适用于具有混合值类型的数组。
对于不支持本地方法filter
和indexOf
的旧浏览器(<ie9),您可以在MDN文档中找到解决方法filter和indexOf。
如果要保留值的最后一次出现,请将indexOf
替换为lastIndexOf
。
使用ES6,可以缩短为:
// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((value, index, array) => array.indexOf(value) === index);
console.log(unique); // unique is ['a', 1, 2, '1']
感谢Camilo Martin在评论中的提示。
ES6有一个原生对象Set
用于存储唯一值。现在你可以这样获取一个具有唯一值的数组:
var myArray = ['a', 1, 'a', 2, '1'];
let unique = [...new Set(myArray)];
console.log(unique); // unique is ['a', 1, 2, '1']
Set
的构造函数需要一个可迭代对象,例如一个数组,并且展开运算符 ...
可以将 Set 转换回数组。感谢 Lukas Liese 在评论中提供的提示。
.filter((v,i,a)=>a.indexOf(v)==i)
表示筛选出数组中不重复的元素(使用箭头函数语法)。 - Camilo MartinArray.from(new Set([[1,2],[1,2],[1,2,3]]))
。 - Alexander GoncharovSet
并添加对象而不是原始值,则其中包含对对象的唯一引用。因此,在let s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);
中,集合s
将返回Set { { Foo: 'Bar' }, { Foo: 'Bar' } }
,这是一个包含相同值的对象的唯一对象引用的Set
。如果你写let o = {Foo:"Bar"};
,然后像这样创建两个引用的集合:let s2 = new Set([o,o]);
,那么s2
将是Set { { Foo: 'Bar' } }
。 - mortbArray.from( new Set( items ) )
。 - Lee Goddard我将所有答案分为4种可能的解决方案:
{ }
防止重复[ ]
filter + indexOf
Sets
方法。以下是在答案中找到的示例代码:
{ }
防止重复function uniqueArray1( ar ) {
var j = {};
ar.forEach( function(v) {
j[v+ '::' + typeof v] = v;
});
return Object.keys(j).map(function(v){
return j[v];
});
}
[ ]
function uniqueArray2(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
a.push(arr[i]);
return a;
}
filter + indexOf
function uniqueArray3(a) {
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
// usage
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']
return unique;
}
[...new Set(a)]
function uniqueArray4(a) {
return [...new Set(a)];
}
我曾经想知道哪个更快。我制作了一个Google表格来测试函数。注意:Google Sheets不支持ECMA 6,所以无法进行测试。
我希望看到使用对象{}
的代码会赢,因为它使用哈希。所以我很高兴这些测试在Chrome和IE中显示了这个算法的最佳结果。感谢@rab提供代码。
Google脚本已启用ES6引擎。现在我测试了最后的代码,使用Sets
比对象方法更快。
uniqueItems = [...new Set(items)]
这种方式似乎是所有方法中最快且最简洁的? - VassuniqueItems = [...new Set(items)]
是最快的方法。 - João Pimentel FerreiraObject.values(j);
- Tayskyconsole.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>
这将返回:
[1, 2, 3, 4]
array = [...new Set(array)]
即可完成一个小任务。 - user6269864_.uniqWith(arrayOfObjects, _.isEqual)
。_.uniqWith([{a: 2}, {b: 3}, {a: 2}], _.isEqual)
将返回 [{a: 2}, {b: 3}]
。 - Aronuniq()
函数了。所以,即使它不是同一个库,感谢你提供的信息! - brandizziSet
去除重复项。
带有重复项的 Array
。const withDuplicates = [2, 2, 5, 5, 1, 1, 2, 2, 3, 3];
使用Set获取没有重复项的新数组
const withoutDuplicates = Array.from(new Set(withDuplicates));
一种更短的版本const withoutDuplicates = [...new Set(withDuplicates)];
结果:[2, 5, 1, 3]
这里的许多答案可能对初学者不太有用。如果去重一个数组很困难,他们真的会知道原型链,甚至是jQuery吗?
在现代浏览器中,一个简单而干净的解决方案是将数据存储在Set中,它被设计为一个唯一值列表。
const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
const uniqueCars = Array.from(new Set(cars));
console.log(uniqueCars);
Array.from
函数非常有用,可以将Set转换为Array,这样就可以轻松访问数组的所有方法和特性。还有其他方法可以实现相同的功能,具体可参考这里。但你可能根本不需要使用Array.from
,因为Set已经拥有许多有用的特性,例如forEach。
如果需要支持旧版Internet Explorer,无法使用Set,则可以采用简单的技巧,将项目复制到新数组中,并在此之前检查它们是否已经存在于新数组中。
// Create a list of cars, with duplicates.
var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
// Create a list of unique cars, to put a car in if we haven't already.
var uniqueCars = [];
// Go through each car, one at a time.
cars.forEach(function (car) {
// The code within the following block runs only if the
// current car does NOT exist in the uniqueCars list
// - a.k.a. prevent duplicates
if (uniqueCars.indexOf(car) === -1) {
// Since we now know we haven't seen this car before,
// copy it to the end of the uniqueCars list.
uniqueCars.push(car);
}
});
function deduplicate(data) {
if (data.length > 0) {
var result = [];
data.forEach(function (elem) {
if (result.indexOf(elem) === -1) {
result.push(elem);
}
});
return result;
}
}
var uniqueCars = deduplicate(cars);
deduplicate(cars)
部分在函数完成后会成为我们命名为result的东西。
只需将任何数组的名称传递给它即可。["volvo","lincoln"]
。 - JasonMap
来存储之前出现过的项,以及一个数组来存储重复的项。然后循环遍历 cars
数组并检查 Map 是否有当前项,如果有,则将其推送到重复项数组中,如果没有,则将其添加到 Map 中。如果您创建一个新问题,我们可以在那里继续讨论,我很乐意为您创建一个代码示例。 - Seth Holladayset
方法作为数组原型的扩展。 - johny whyArray.prototype
是一种不好的做法,并且强烈建议不要这样做。除了其他原因外,如果将来在语言中添加新的方法,这样做可能会导致未来出现错误。事实上,如果您的网站很受欢迎,甚至可能阻止将来向语言中添加新方法。这实际上已经发生过。请参见:https://2ality.com/2022/03/naming-conflicts.html - Seth Holladay使用 ES6 的 new Set
var array = [3,7,5,3,2,5,2,7];
var unique_array = [...new Set(array)];
console.log(unique_array); // output = [3,7,5,2]
使用 For Loop
var array = [3,7,5,3,2,5,2,7];
for(var i=0;i<array.length;i++) {
for(var j=i+1;j<array.length;j++) {
if(array[i]===array[j]) {
array.splice(j,1);
}
}
}
console.log(array); // output = [3,7,5,2]
我后来发现了一个使用jQuery的不错方法
arr = $.grep(arr, function(v, k){
return $.inArray(v ,arr) === k;
});
注意:此代码来自Paul Irish的鸭子补丁文章-我忘记给他点赞了:P
a.filter( e => !(t[e]=e in t) )
O(n) 性能 - 我们假设你的数组在 a
中,t={}
。解释 这里 (+Jeppe impr.)
let unique = (a,t={}) => a.filter(e=>!(t[e]=e in t));
// "stand-alone" version working with global t:
// a1.filter((t={},e=>!(t[e]=e in t)));
// Test data
let a1 = [5,6,0,4,9,2,3,5,0,3,4,1,5,4,9];
let a2 = [[2, 17], [2, 17], [2, 17], [1, 12], [5, 9], [1, 12], [6, 2], [1, 12]];
let a3 = ['Mike', 'Adam','Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];
// Results
console.log(JSON.stringify( unique(a1) ))
console.log(JSON.stringify( unique(a2) ))
console.log(JSON.stringify( unique(a3) ))
for
循环以外的其他结构中也可以使用in
运算符:P)- 谢谢 - 我很感激,并会给你其他好答案+2。 - Kamil Kiełczewski
o
表示对象
,a
表示数组
,i
表示索引
,而e
则表示嗯,某个东西:P - Mottie