web-dev-qa-db-ja.com

フラットリストからツリーへのJavaScript関数変換

私はRxJSチュートリアル http://reactivex.io/learnrx/ を行ってきました。ほとんどすべての演習は、階層構造からフラット構造への移行を伴うため、私は反対のことをしようと思いました。

チュートリアルの同じ機能構成体を使用して、各配列項目のプロパティに基づいてフラット配列からツリー構造に変換したいと思います。

つまりこれから行く:

var videos = [
    {
        "id": 70111470,
        "title": "Die Hard",
        "category": "Action"
    },
    {
        "id": 654356453,
        "title": "Bad Boys",
        "category": "Action"
    },
    {
        "id": 65432445,
        "title": "Anchorman",
        "category": "Comedy"
    },
    {
        "id": 675465,
        "title": "Everest",
        "category": "New Release"
    }
];

これには(各ビデオのカテゴリに基づく):

result === [
    {
        "category": "Action",
        "videos": [
            {
                "id": 70111470,
                "title": "Die Hard"
            },
            {
                "id": 654356453,
                "title": "Bad Boys"
            }
        ]
    },
    {
        "category": "Comedy",
        "videos": [
            {
                "id": 65432445,
                "title": "Anchorman"
            }
        ]
    },
    {
        "category": "New Release",
        "videos": [
            {
                "id": 675465,
                "title": "Everest"
            }
        ]
    }
];

機能する次のコードを考え出しましたが、(ビデオを何度もフィルタリングするのではなく)パフォーマンスが向上する簡単な方法(おそらく単一の削減で解決する)が足りないようです。

var result = 
    videos.reduce(function(catArray, video) {
       var catName = video.category;
       if (catArray.indexOf(catName) === -1) {
          catArray.Push(catName);
       }
       return catArray;
    }, [])
    .map(function(categoryName) {
        return {
            category: categoryName,
            videos: videos.filter(function(video) {
                        return video.category === categoryName;
                    }).map(function(video) {
                        return {
                            id: video.id,
                            title: video.title
                        };
                    })
        };
    });

関数型メソッドを使用するより良い方法はありますか?

3
Glenn Allen

結果はレベルを1つしか持てないため、ツリーよりも簡単です。必要なのは、配列をカテゴリ別にグループ化し、各グループをオブジェクトにマッピングすることだけです。マップパーツは、最終的な目的の構造に少し変更するだけです。現在行っているように、マップ内のvideosの完全なリストをフィルタリングする必要はありません。

残念ながら、JavaScriptはデフォルトで機能パラダイムに特に友好的ではないので、組み込みgroupByがありません。そのため、reduce内でグループ化を再実装するか、 Ramda のような外部ライブラリからグループ化を使用できます。そこにあるサンプルコードは、groupByの仕組みを理解するのに役立ちます。

3