0

varにオブジェクトの配列がある場合。特定のプロパティごとにグループ化されるように、これを減らしたいと思います。これは私のコードです

array = tracks.reduce (x,y,i) ->
    x[y.album] = []
    x
, {}

albums = tracks.reduce (x,y,i) ->
    array[y.album].push {'name':y.name, 'mp3':y.mp3}
    array
, {}


console.log(albums)

それは私が望むものを出力します、しかし私はグループのために空の配列を作成するために最初のループをする必要なしにこれを書くより良い方法があるかどうか知りたいです。

ありがとう。

4

1 に答える 1

4

はい、or=or?=演算子を使用して割り当てることができるのは、array[y.ambum]初期化されていない場合のみです。したがって、1 つのループのみを使用します。ところで、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 プロパティだけではありません)。


更新:パフォーマンスに関するコメント:「効率的に」何かをするように頼まれたとき、私はそれを可能な限り最も直接的でクリーンな方法で行うと解釈します(コードを読むときのプログラマーの効率について考えています); しかし、多くの人は明確に効率をパフォーマンスに関連付けます。

パフォーマンスについては、これら 3 つのソリューションはすべて O(n) であり、n はトラックの数であり、複雑です。どちらも他のものよりひどく悪いわけではありません。

生のforループは、同等の高次の兄弟forEachである、 などよりも最新の JS エンジンで高速に実行されるようreduceです(これは非常に悲しいことです :(...)。したがって、最初のバージョンは 2 番目のバージョンよりも高速に実行されるはずです。

Underscore バージョンの場合、Underscore は生のループの代わりに高次関数を多くfor使用することで知られているため、予測は行いませんが、同時に、そのバージョンはトラックごとに新しいオブジェクトを作成しません。 .

いずれにせよ、パフォーマンスは向上するが読みにくいソリューションにソリューションを変更する前に、必ずコードをプロファイリングする必要があります。その特定のループがボトルネックであることに気付き、それをベンチマークするための適切なデータ セットがある場合、jsPerfは非常に便利です:)

于 2013-01-29T16:06:30.133 に答える