是的,只有在没有初始化的情况下才可以使用or=
or?=
运算符进行赋值;array[y.ambum]
因此只使用一个循环。顺便说一句,我认为array
变量是一个对象有点令人困惑。另一种使用 CoffeeScript 循环而不是编码的方法reduce
是:
albums = {}
for {album, name, mp3} in tracks
(albums[album] or= []).push {name, mp3}
请注意,我正在使用解构来一次获取所有轨道属性。
或者,如果您想使用reduce
:
albums = tracks.reduce (albums, {album, name, mp3}) ->
(albums[album] or= []).push {name, mp3}
albums
, {}
但我认为 CS-loop 版本读起来更好:)
奖励曲目(双关语):如果您碰巧有 Underscore.js,我强烈建议您使用groupBy
,这正是这种分组工作:
albums = _.groupBy tracks, (track) -> track.album
请注意,每个专辑名称的曲目albums
将是“完整的”曲目(不仅仅是名称和 mp3 属性)。
更新:关于性能的评论:当被要求“有效地”做某事时,我将其解释为以最直接和最干净的方式做事(我在考虑程序员在阅读代码时的效率);但许多人会明确地将效率与绩效联系起来。
关于性能,这三个解决方案都是 O(n),n 是轨道数,复杂度;所以两者都没有比其他人差得可怕。
似乎原始for
循环在现代 JS 引擎上的运行速度比其等效的高阶兄弟:forEach
、、reduce
等(这让 IMO 感到非常难过 :(...)。所以第一个版本应该比第二个版本运行得更快。
对于 Underscore 版本,我不会做任何预测,因为 Underscore以大量使用高阶函数而不是原始for
循环而闻名,但同时,该版本不会为每个轨道创建一个新对象.
在任何情况下,在将解决方案更改为性能更高但可读性较差的解决方案之前,您都应该始终分析您的代码。如果您注意到该特定循环是一个瓶颈,并且您有一组很好的数据来对其进行基准测试,那么jsPerf会非常有用:)