假设我有以下内容:
var array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
能够获得所有不同年龄的数组的最佳方法是什么,以便我得到一个结果数组:
[17, 35]
有没有办法我可以选择构造数据或更好的方法,这样我就不必遍历每个数组检查“age”的值并检查另一个数组是否存在,如果没有则添加它?
如果有某种方式我可以在没有迭代的情况下拉出不同的年龄......
我希望改进的当前无效方式......如果它意味着不是“数组”是一个对象数组,而是一个具有一些唯一键(即“1,2,3”)的对象的“映射”好的我只是在寻找性能最高效的方式 .
以下是我目前的工作方式,但对我而言,迭代看起来效率低下,即使它确实有效......
var distinct = []
for (var i = 0; i < array.length; i++)
if (array[i].age not in distinct)
distinct.push(array[i].age)
26 回答
这是你如何使用新的Set by ES6 for Typescript解决这个问题,截至2017年8月25日
使用ES6功能,您可以执行以下操作:
我只是映射并删除重复:
Edit: Aight!在性能方面不是最有效的方式,而是最简单最易读的IMO . 如果您真的关心微优化或者您拥有大量数据,那么常规
for
循环将会更加"efficient" .如果这是PHP,我会使用键构建一个数组并在最后获取
array_keys
,但JS没有这样的奢侈品 . 相反,试试这个:如果您使用的是ES6 / ES2015或更高版本,则可以这样做:
Here是一个如何做的例子 .
您可以使用像这样的字典方法 . 基本上,您将要分隔的值指定为字典中的键 . 如果密钥不存在,则将该值添加为不同 .
这是一个有效的演示:http://jsfiddle.net/jbUKP/1
这将是O(n),其中n是数组中对象的数量,m是唯一值的数量 . 没有比O(n)更快的方法,因为你必须至少检查一次每个值 .
Performance
http://jsperf.com/filter-versus-dictionary当我运行这本词典的速度提高了30% .
使用ES6
@ travis-j的
forEach
版本答案(对现代浏览器和Node JS世界有帮助):Chrome v29.0.1547的速度提高34%:http://jsperf.com/filter-versus-dictionary/3
并且采用映射器函数的通用解决方案(比直接映射慢,但这是预期的):
我默认开始在所有新项目中坚持Underscore所以我永远不必考虑这些小数据纠正问题 .
产生
[17, 35]
.使用lodash
这是解决此问题的另一种方法:
我不知道这个解决方案与其他解决方案相比有多快,但我喜欢更干净的外观 . ;-)
编辑:好的,上面似乎是所有这里最慢的解决方案 .
我在这里创建了一个性能测试用例:http://jsperf.com/distinct-values-from-array
我没有测试年龄(整数),而是选择比较名称(字符串) .
方法1(TS的解决方案)非常快 . 有趣的是,方法7优于所有其他解决方案,在这里我只是摆脱了.indexOf()并使用了它的“手动”实现,避免了循环函数调用:
使用Safari和Firefox的性能差异令人惊叹,Chrome似乎在优化方面做得最好 .
我不完全确定为什么上述片段与其他片段相比如此之快,也许比我更聪明的人有答案 . ;-)
underscore.js
_.uniq(_.pluck(array,"age"))
使用Lodash
退货[17,35]
我认为你正在寻找groupBy功能(使用Lodash)
产生结果:
jsFiddle演示:http://jsfiddle.net/4J2SX/201/
已经有很多有效的答案,但我想添加一个只使用
reduce()
方法的答案,因为它简洁明了 .像这样用它:
刚发现这个,我觉得它很有用
再次使用underscore,所以如果你有这样的对象
它只会给你独特的对象 .
这里发生的是
indexBy
返回这样的 Map而且因为它是一张 Map ,所有的钥匙都是独一无二的 .
然后我只是将这个列表映射回数组 .
如果您只需要不同的值
请记住
key
以字符串形式返回,因此,如果您需要整数,则应该这样做如果您有Array.prototype.includes或愿意polyfill它,这适用:
如果像我一样你更喜欢更“功能”而不影响速度,这个例子使用包含在reduce闭包内的快速字典查找 .
根据这个test,我的解决方案的速度是建议答案的两倍
这是一个多功能的解决方案,使用reduce,允许映射和维护插入订购 .
items:一个数组
mapper:将项目映射到条件的一元函数,或者为映射项目本身的空白 .
用法
您可以将它添加到您的Array原型中,如果这是您的风格,则省略items参数...
您还可以使用Set而不是Array来加速匹配 .
使用新的Ecma功能非常棒,但并非所有用户都拥有这些功能 .
下面的代码将一个名为 distinct 的新函数附加到Global Array对象 . 如果您尝试获取对象数组的不同值,则可以传递值的名称以获取该类型的不同值 .
查看CodePen中的my post进行演示 .
试一试
我对此功能的两分钱:
你可以在这里看到结果(方法8)http://jsperf.com/distinct-values-from-array/3
使用d3.js v3:
这个函数可以是唯一的数组和对象
使用这样的