質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.03%

Laravelのコレクションで多次元配列の辞書データを作成したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,646

macharu

score 22

Laravelに詳しい方助けてください!

表題の通りLaravelのコレクションで多次元配列の辞書データを作成したいです。

具体的に説明すると、まず下記のようなテーブルが存在するとします。

id product_id date type count
1 1001 2018-08-01 in 11
2 1002 2018-08-02 in 3
3 1003 2018-08-03 in 4
4 1002 2018-08-04 out 5
5 1001 2018-08-05 in 8
6 1002 2018-08-06 out 9
7 1003 2018-08-07 in 10

品物の入出庫データのようなものをイメージしていただくとわかりやすいかと思います。

便宜上idのカラムが存在しますが、このテーブルは「product_id、date、type」の3つのカラムの複合キーでこの3つの組み合わせが重複することはありません。

このテーブルからデータを取得して連想配列の辞書データを作りたいのですがうまくいきません。

色々調べてみて下記のコードを試してみたのですが、

$dictionary = App\HogeTable
            ->whereDate('date', '>=','2018-08-01')
            ->whereDate('date', '<=','2018-08-31')
            ->get()->mapToDictionary(function ($item) {
                return [
                    $item['date'] => [
                        $item['product_id'] => [
                            $item['type'] => $item['count']
                        ]
                    ]
                ];
            })->toArray();

この$dictionaryを出力すると、下記のような形で、date以下にproduct_idがキーとなる配列が作成されません。

array (size=31)
  '2018-08-29' => 
    array (size=30)
      0 => 
        array (size=1)
          1261 => 
            array (size=1)
              ...
      1 => 
        array (size=1)
          1259 => 
            array (size=1)
              ...
      2 => 
        array (size=1)
          1258 => 
            array (size=1)
              ...
      3 => 
        array (size=1)
          1265 => 
            array (size=1)

最終的に$dictionary[date][product_id][type]で任意のcountを取得できるような配列を生成したいのですが、うまい方法はないでしょうか?

どなたかお力添えいただけますと助かります!

参考URL
https://qiita.com/nunulk/items/ef82a35aa2b75200afa3#52-maptodictionary-55

Laravelのバージョンは5.5です。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

dateについてgroup化してからmapしてproduct_idについてgroup化して...のようにする方法もありますが、この場合はeachを使った方が簡潔でわかりやすいと思います。

        $dictionary = [];
        App\HogeTable::whereDate('date', '>=', '2018-08-01')
            ->whereDate('date', '<=', '2018-08-31')
            ->get()
            ->each(function ($item) use (&$dictionary) {
                $dictionary[$item['date']][$item['product_id']][$item['type']] = $item['count'];
            });

最初に書いたやり方だとこんな感じ。

        $dictionary = App\HogeTable::whereDate('date', '>=', '2018-08-01')
            ->whereDate('date', '<=', '2018-08-31')
            ->get()
            ->groupBy('date')
            ->map(function ($byDate) {
                return $byDate
                    ->groupBy('product_id')
                    ->map(function ($byProductId) {
                        return $byProductId
                            ->groupBy('type')
                            ->map(function ($byType) {
                                return $byType->first()['count'];
                            })
                            ->all();
                    })
                    ->all();
            })
            ->all();

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/06 13:55

    おお、完璧です!
    そんなやり方があるんですね

    これで期待通りの結果を得ることができました。助かりました!ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる