我有一系列数字,我需要确保它们是唯一的 . 我在互联网上找到了下面的代码片段,它的工作原理很好,直到数组中的数字为零 . 我发现this other script在这里看起来几乎完全一样,但它并没有失败 .
所以为了帮助我学习,有人可以帮我确定原型脚本出错的地方吗?
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;
}
30 回答
我们可以使用ES6集来做到这一点:
//输出将是
我发现序列化他们的哈希键帮助我实现了对象的工作 .
你也可以使用underscore.js .
将返回:
我后来发现了一个使用jQuery的好方法
注意:此代码是从Paul Irish's duck punching post中提取的 - 我忘了给予赞誉:P
以简单的方法查找唯一的Array值
如果有人使用knockoutjs
BTW已经查看了所有
ko.utils.array*
实用程序 .要反过来解决这个问题,在加载数组时没有重复可能会很有用,Set对象会这样做,但它还没有在所有浏览器中都可用 . 如果您需要多次查看其内容,它可以节省内存并提高效率 .
样品:
给你
set = [1,3,4,2]
如果你为'循环,你可以像这样使用http://www.prototypejs.org/api/array/uniq:
这将生成一个没有重复的重复数组 . 我遇到了一个问题,搜索一个方法来计算不同的数组记录
我用了
这是我的简单结果 . 附:对不起,如果我错误的输入了什么
编辑:如果要转义未定义的记录,可能需要添加
之前,像这样:
奇怪的是之前没有建议..要删除数组中的对象键(下面的
id
)重复项,你可以这样做:如果没有扩展Array.prototype(它被认为是一种不好的做法)或使用jquery / underscore,你可以简单地
filter
数组 .保留最后一次:
或第一次出现:
好吧,它只是javascript ECMAScript 5,这意味着只有IE9,但它适用于原生HTML / JS(Windows应用商店应用,Firefox OS,Sencha,Phonegap,Titanium等)的开发 .
最简单的解决方案
要么:
使用对象键来制作独特的数组,我试过以下
返回
["1", 1, 2, 3, 4, "foo", false, null]
使用JavaScript 1.6 / ECMAScript 5,您可以通过以下方式使用Array的本机filter方法来获取具有唯一值的数组:
本机方法
filter
将遍历数组并仅保留那些通过给定回调函数onlyUnique
的条目 .onlyUnique
检查,如果给定的值是第一次发生 . 如果没有,则必须是重复的,不会被复制 .此解决方案无需任何额外的库,如jQuery或prototype.js .
它适用于具有混合值类型的数组 .
对于不支持本机方法
filter
和indexOf
的旧浏览器(<ie9),您可以在filter和indexOf的MDN文档中找到解决方法 .如果要保留最后一次出现的值,请简单地将
indexOf
替换为lastIndexOf
.使用ES6可以缩短到这一点:
感谢Camilo Martin提供评论提示 .
ES6有一个本机对象Set来存储唯一值 . 要获得具有唯一值的数组,您现在可以执行以下操作:
Set
的构造函数采用可迭代对象(如Array),并且扩展运算符...
将该集转换回数组 . 感谢Lukas Liese提示评论 .你也可以使用jQuery
最初回复于:jQuery function to get all unique elements from an array?
我意识到这个问题已有30多个答案 . 但我先阅读了所有现有的答案并进行了自己的研究 .
我将所有答案分成4个可能的解决方案:
使用新的ES6功能:
[...new Set( [1, 1, 2] )];
使用对象
{ }
来防止重复使用辅助数组
[ ]
使用
filter + indexOf
以下是答案中的示例代码:
使用新的ES6功能:[...新设置([1,1,2])];
使用对象{}来防止重复
使用辅助数组[]
使用过滤器indexOf
我想知道哪一个更快 . 我已经sample Google Sheet来测试功能 . 注意:ECMA 6在Google表格中不可用,因此我无法对其进行测试 .
这是测试的结果:
我希望看到使用对象
{ }
的代码将获胜,因为它使用哈希 . 所以我很高兴测试在Chrome和IE中显示了该算法的最佳结果 . 感谢@rab for the code .这里的许多答案可能对初学者没用 . 如果难以对数组进行重复数据删除,他们真的会知道原型链,甚至是jQuery吗?
在现代浏览器,一个干净而简单的解决方案是将数据存储在Set中,该数据被设计为唯一值列表 .
Array.from
对于将Set转换回Array非常有用,这样您就可以轻松访问数组所具有的所有令人敬畏的方法(功能) . 还有other ways做同样的事情 . 但是你可能根本不需要Array.from
,因为集合有很多有用的功能,如forEach .如果您需要支持旧的Internet Explorer,因此无法使用Set,那么一种简单的技术是将项目复制到新阵列,同时事先检查它们是否已经在新阵列中 .
为了使它可以立即重用,让我们把它放在一个函数中 .
因此,为了摆脱重复,我们现在就这样做 .
deduplicate(cars)
部分 becomes 我们在函数完成时命名的结果 .只需传递你喜欢的任何数组的名称 .
那是因为
0
是JavaScript中的虚假值 .如果数组的值为0或任何其他假值,则
this[i]
将是假的 .One Liner,Pure JavaScript
With ES6 syntax
list = list.filter((x, i, a) => a.indexOf(x) == i)
With ES5 syntax
Browser Compatibility :IE9
这个原型
getUnique
并不完全正确,因为如果我有一个像这样的数组:["1",1,2,3,4,1,"foo"]
它将返回["1","2","3","4"]
并且"1"
是字符串而1
是一个整数;它们是不同的 .这是一个正确的解决方案:
使用:
以上将产生
["1",2,3,4,1,"foo"]
.这会奏效 .
PERFORMANCE ONLY! this code is probably 10X faster than all the codes in here *适用于所有浏览器,并且内存影响最小....等等
如果你不需要重用旧的数组;顺便说一句,在你将它转换为唯一之前做必要的其他操作,这可能是最快的方法,也很短 .
然后你可以试试这个
我想出了这个函数阅读这篇文章......
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
我不喜欢for循环 . 它有许多参数 . 我喜欢while--循环 . 虽然是所有浏览器中最快的循环,除了我们都非常喜欢的那个... chrome .
无论如何我写了第一个使用while的函数 . 是的,它比文章中的函数快一点 . 但还不够 .
unique2()
下一步使用现代js .
Object.keys
我用js1.7的Object.keys替换了另一个for循环...更快更短(在chrome中快了2倍);) . 不够! .unique3()
.在这一点上,我正在思考我在我独特功能中真正需要的东西 . 我不需要旧的阵列,我想要一个快速的功能 . 所以我使用2 while循环拼接 .
unique4()
Useless to say that i was impressed.
chrome:通常每秒150,000次操作跃升至每秒1,800,000次操作 .
即:80,000 op / s vs 3,500,000 op / s
ios:18,000 op / s vs 170,000 op / s
safari: 80,000 op/s vs 6,000,000 op/s
Proof http://jsperf.com/wgu或更好地使用console.time ... microtime ......无论如何
unique5()
只是为了告诉你如果要保留旧数组会发生什么 .如果你不知道你在做什么,请不要使用
Array.prototype
. 我刚做了很多副本和过去 . 如果要创建本机prototype.example,请使用Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})
:https://stackoverflow.com/a/20463021/2450730Demo http://jsfiddle.net/46S7g/
NOTE: your old array is destroyed/becomestheunique after this operation.
如果你不能阅读上面的代码问,请阅读javascript书或这里有一些关于更短代码的解释 . https://stackoverflow.com/a/21353032/2450730
有些人正在使用
indexOf
...不要...... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh对于空数组
从Shamasis Bhattacharya's blog(O(2n)时间复杂度):
来自Paul Irish's blog:改进JQuery .unique():
你也可以用sugar.js:
Updated answer for ES6/ES2015 :使用Set,单行解决方案是:
哪个回报
正如le_m建议的那样,这也可以使用spread operator缩短,就像
最简单的,以及在Chrome中执行此操作的方式:
只需遍历数组中的每个项目,测试该项目是否已在列表中,如果不是,则推送到返回的数组 .
根据jsPerf,这个函数是the fastest of the ones I could find anywhere - 随意添加你自己的功能 .
非原型版:
排序
当还需要对数组进行排序时,以下是最快的:
或非原型:
在大多数非Chrome浏览器中,这也是faster than the above method .
我不确定为什么加布里埃尔·西尔维拉(Gabriel Silveira)用这种方式编写函数,但是一个对我来说同样适用的简单形式,并且没有缩小:
或者在CoffeeScript中:
在其他答案的基础上,这是另一个变量,它采用可选标志来选择策略(保持第一次出现或保持最后):
Without extending
Array.prototype
Extending
Array.prototype
ES6的最短解决方案:
[...new Set( [1, 1, 2] )];
或者,如果要修改Array原型(如原始问题中所示):
目前(2015年8月),现代浏览器中的EcmaScript 6仅为partially implemented,但是Babel已经变得非常受欢迎将ES6(甚至是ES7)转发回ES5 . 这样你今天就可以编写ES6代码了!
如果你想知道
...
的意思,它叫做spread operator . 从MDN:«扩展运算符允许在多个参数(用于函数调用)或多个元素(用于数组文字)的位置扩展表达式» . 因为Set是可迭代的(并且只能具有唯一值),所以扩展运算符将展开Set以填充数组 .学习ES6的资源:
由Axel Rauschmayer博士撰写的
来自JS每周通讯的
来自Mozilla Hacks博客的