5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScriptでオブジェクトの配列をグループ分け(groupby)して表示する

Last updated at Posted at 2019-07-27

以下のように配列が与えられている時に、重複しているものをカテゴリ分けして、それぞれに紐づくプロパティの値を子要素として出力させる結果を得たいと思った。(画像①のようなイメージ)

constant.js
    const fruits = [{
            name: 'apple',
            price: 100
        },
        {
            name: 'apple',
            price: 500
        },
        {
            name: 'apple',
            price: 1000
        },
        {
            name: 'banana',
            price: 100
        },
        {
            name: 'banana',
            price: 300
        },
        {
            name: 'banana',
            price: 500
        },
        {
            name: 'banana',
            price: 700
        },
        {
            name: 'orange',
            price: 100
        },
        {
            name: 'orange',
            price: 300
        },
    ];

画像①
Screen Shot 2019-07-27 at 22.03.28.png

アプローチとしては以下。
1.配列のプロパティの値が全部で何種類なのか検出する
2.それぞれのpriceを配列として更にグループ分け
3.二重のfor文で表示させる

以下のようなコードを買いたところ、期待通りの結果を得ることが出来た。

index.js

    function fruitArrGroupBy(list, keyGetter) {
        const map = new Map();
        list.forEach((item) => {
            const key = keyGetter(item);
            const collection = map.get(key);
            if (!collection) {
                map.set(key, [item]);
            } else {
                collection.push(item);
            }
        });
        return map;
    }
    var groupedFruitArr = fruitArrGroupBy(fruits, fruit => fruit.name);
    
    //配列のキーが何種類あるのかを出す(重複を外した配列を生成する)
    var fruitTypeList = fruits.filter(function(v1,i1,a1){ 
        return (a1.findIndex(function(v2){ 
            return (v1.name===v2.name) 
        }) === i1);
    });

    //HTMLにレンダリング
    for (let i = 0; i < fruitTypeList.length; i++) {
        $("body").append(`<h1>${fruitTypeList[i].name}</h1>
                           <ul class="wrapper${i}"></ul>`);
        $("body").append(``);
        var fruitItemArray = groupedFruitArr.get(`${fruitTypeList[i].name}`);
        for(var j = 0;j < fruitItemArray.length ;j++){
            $(`.wrapper${i}`).append(`<li>${fruitItemArray[j].price}円</li>`)
        }
    }

しかし、もっとコードを改良出来るのではと思い信頼のおける先輩に相談したところ、親切に色々とフィードバックいただき、ここまで短くすることができた。
(※大きな表示の変更は変わらないという前提で)

index.js
        var fruitsObj = {};
        var fruitsObjArr = [];
        // fruitsObj[number] = { name: 'Newcomer!' },
        for (var k = 0; k < fruits.length; k++) {
            //キー名に配列の値が無かったら
            if (fruits[k].name in fruitsObj != true) fruitsObjArr = [];
            fruitsObjArr.push(fruits[k].price);
            console.log(fruitsObjArr);
            fruitsObj[fruits[k].name] = fruitsObjArr;
        }
        console.log(fruitsObj);

        for (const key in fruitsObj) {
            $('body').append(`<h1>${key}</h1><ul class="wrapper-${key}"></ul>`);
            if (fruitsObj.hasOwnProperty(key)) {
                for (let i = 0; i < fruitsObj[key].length; i++) {
                    $(`.wrapper-${key}`).append(`<li>${fruitsObj[key][i]}円</li>`)   
                }
            }
        }
5
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?