所以为了帮助我学习,有人可以帮我确定原型脚本出了什么问题吗?
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;
}
我们可以使用ES6集合(set)来完成这个操作:
var duplicatesArray = [1, 2, 3, 4, 5, 1, 1, 1, 2, 3, 4];
var uniqueArray = [...new Set(duplicatesArray)];
console.log(uniqueArray); // [1,2,3,4,5]
做这件事最简单、最快(在Chrome浏览器中)的方法如下:
Array.prototype.unique = function() {
var a = [];
for (var i=0, l=this.length; i<l; i++)
if (a.indexOf(this[i]) === -1)
a.push(this[i]);
return a;
}
该函数遍历数组中的每个项,测试该项是否已经在列表中,如果不在,则将其推送到要返回的数组中。
根据JSBench的测试,此函数是我能找到的最快的函数 - 当然,您可以添加自己的函数。
非原型版本:
function uniques(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;
}
如果需要对数组进行排序,以下是最快的方法:
Array.prototype.sortUnique = function() {
this.sort();
var last_i;
for (var i=0;i<this.length;i++)
if ((last_i = this.lastIndexOf(this[i])) !== i)
this.splice(i+1, last_i-i);
return this;
}
或非原型:
function sortUnique(arr) {
arr.sort();
var last_i;
for (var i=0;i<arr.length;i++)
if ((last_i = arr.lastIndexOf(arr[i])) !== i)
arr.splice(i+1, last_i-i);
return arr;
}
在大多数非Chrome浏览器中,这种方法也比上述方法更快。
unique
函数中实现的算法复杂度为 O(n^2),而在 getUnique
中则为 O(n)。第一个算法在小数据集上可能更快,但数学不会说谎 :) 如果您在由1e5个独特项组成的数组上运行这两个函数,则可以确保后者更快。 - Mikhail Dudininput_array.length < 200
,否则使用[...new Set(input_array)]
方法。表达为reducer:input_array.reduce((c, v) => {if (!c.includes(v)) c.push(v); return c;}, [])
。 - milahu["Defects", "Total", "Days", "City", "Defects"].reduce(function(prev, cur) {
return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
}, []);
[0,1,2,0,3,2,1,5].reduce(function(prev, cur) {
return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
}, []);
[].reduce((p, c) => (p.some((item) => c.id === item.id) ? p : p.concat(c)), [])
- Alonso Urbano这个问题已经有很多答案了,但并没有解决我的特定需求。
许多答案都是这样的:
a.filter((item, pos, self) => self.indexOf(item) === pos);
但是这不适用于复杂对象的数组。
假设我们有这样一个数组:
const a = [
{ age: 4, name: 'fluffy' },
{ age: 5, name: 'spot' },
{ age: 2, name: 'fluffy' },
{ age: 3, name: 'toby' },
];
如果我们想要带有唯一名称的对象,应该使用array.prototype.findIndex
而不是array.prototype.indexOf
:
a.filter((item, pos, self) => self.findIndex(v => v.name === item.name) === pos);
indexOf
解决方案,但findIndex
解决方案可能很有用。 - Dave在查看这里的90+个答案后,我发现还有一个解决方案:
Array.includes有一个非常方便的第二个参数:"fromIndex",因此通过使用它,filter
回调方法的每次迭代都会从数组中搜索,从[当前索引]+1
开始,这确保不包括当前已过滤的项在查找中并节省时间。
注意-此解决方案不保留顺序,因为它从左到右删除重复的项,但如果数组是对象的集合,则胜过
Set
技巧。
//
var list = [0,1,2,2,3,'a','b',4,5,2,'a']
console.log(
list.filter((v,i) => !list.includes(v,i+1))
)
// [0,1,3,"b",4,5,2,"a"]
例如,假设filter
函数当前正在迭代索引2
的值恰好为2
。然后扫描数组中包含重复项(使用includes
方法)的那一部分是从索引i+1
开始的所有元素:
[0, 1, 2, 2 ,3 ,'a', 'b', 4, 5, 2, 'a']
|---------------------------|
由于当前被过滤项的值2
包含在数组的其余部分中,因此它将被过滤掉,因为有一个感叹号标记,它否定了过滤规则。
//
var list = [0,1,2,2,3,'a','b',4,5,2,'a']
console.log(
// Initialize with empty array and fill with non-duplicates
list.reduce((acc, v) => (!acc.includes(v) && acc.push(v), acc), [])
)
// [0,1,2,3,"a","b",4,5]
Array.prototype.filter()
和Array.prototype.indexOf()
来实现。
array.filter((x, y) => array.indexOf(x) == y)
var arr = [1, 2, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 6, 9];
var newarr = arr.filter((x, y) => arr.indexOf(x) == y);
console.log(newarr);
这个原型 getUnique
并不完全正确,因为如果我有一个数组,比如["1",1,2,3,4,1,"foo"]
它会返回["1","2","3","4"]
,但是"1"
是字符串而1
是整数,它们是不同的。
以下是正确的解决方案:
Array.prototype.unique = function(a){
return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });
使用:
var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();
以上代码将生成["1",2,3,4,1,"foo"]
。$foo = 'bar'
是 PHP 声明变量的方式。虽然它在 JavaScript 中也可以工作,但会创建一个隐式的全局变量,通常不应该这样做。 - Camilo Martin$foo
是在JavaScript中声明变量的方式,而实际上应该用var foo
。 - Camilo MartinSet
(推荐)var array = ["FreePhoenix888", "FreePhoenix888", "konard", "FreePhoenix888"];
let set = [...new Set(array)];
console.log(set); // ["FreePhoenix888", "konard"]
Set
function filterUniqueObjects(value, index, array) {
return array.indexOf(value) === index;
}
// usage example:
var array = ["FreePhoenix888", "FreePhoenix888", "konard", "FreePhoenix888"];
var arrayOfUniqueItems = array.filter(filterUniqueObjects);
console.log(arrayOfUniqueItems); // ["FreePhoenix888", "konard"]
此示例演示了如何过滤不仅是原始值数组,而是对象数组。我已添加注释,以便根据您的要求更轻松地理解可以更改哪些内容。
let array = [
{ name: '@deep-foundation/core', version: '0.0.2' },
{ name: '@deep-foundation/capacitor-device', version: '10.0.1' },
{ name: '@deep-foundation/capacitor-device', version: '10.0.2' },
];
// Of course you can inline this function as filter argument uniqueArray.filter((item, index, self) => self.findIndex(innerItem => innerItem.name === item.name) === index);
function filterUniqueObjects(value, index, self) {
return (
self.findIndex(
// Modify this function as you desire. You may want to calculate uniqueness depending only on specific fields, not all
(obj) => obj.name === value.name
) === index
);
};
let uniqueArray = array
.reverse() // If you want latest duplicates to remain
.filter(filterUniqueObjects)
.reverse(); // To get back to original order after first reverse
console.log(uniqueArray)
[...new Set(duplicates)]
这是最简单的方法,参考自 MDN Web Docs。
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)]) // [2, 3, 4, 5, 6, 7, 32]
不需要扩展Array.prototype(据说这是一种不好的做法),也不使用jquery/underscore,你可以简单地使用filter
过滤数组。
只保留最后一个出现的:
function arrayLastUnique(array) {
return array.filter(function (a, b, c) {
// keeps last occurrence
return c.indexOf(a, b + 1) < 0;
});
},
或者第一次出现:
function arrayFirstUnique(array) {
return array.filter(function (a, b, c) {
// keeps first occurrence
return c.indexOf(a) === b;
});
},
好的,这只是 Javascript ECMAScript 5+,也就是说只支持 IE9+,但对于原生 HTML/JS 的开发非常有用(Windows Store App,Firefox OS,Sencha,Phonegap,Titanium等)。
filter
。在MDN页面上,他们为Internet Explorer提供了一个实现,也就是说,旧版浏览器。另外:JS 1.6仅指Firefox的js引擎,但正确的说法是它是ECMAScript 5。 - Camilo Martin
o
表示对象
,a
表示数组
,i
表示索引
,而e
则表示嗯,某个东西:P - Mottie