

自分はよく PHP で以下のようにしてデータベースから取得したレコードの変換を行います。

[code]

    <?php
    
    $list = array(
        array("GROUP" => "A", "NAME" => "りんご", "COUNT" => 1),
        array("GROUP" => "A", "NAME" => "ゴリラ", "COUNT" => 2),
        array("GROUP" => "B", "NAME" => "ラッパ", "COUNT" => 3),
    );
    
    $convert_list = array_reduce($list, function($result, $row) {
      if (!key_exists($row["GROUP"], $result)) {
        $result[$row["GROUP"]] = array();
      }
    
      $result[$row["GROUP"]][] = $row;
      return $result;
    }, array());
    
    var_dump($convert_list);
    
[/code]

結果は以下のようになります。

[code]

    array(2) {
      ["A"]=>
      array(2) {
        [0]=>
        array(3) {
          ["GROUP"]=>
          string(1) "A"
          ["NAME"]=>
          string(9) "りんご"
          ["COUNT"]=>
          int(1)
        }
        [1]=>
        array(3) {
          ["GROUP"]=>
          string(1) "A"
          ["NAME"]=>
          string(9) "ゴリラ"
          ["COUNT"]=>
          int(2)
        }
      }
      ["B"]=>
      array(1) {
        [0]=>
        array(3) {
          ["GROUP"]=>
          string(1) "B"
          ["NAME"]=>
          string(9) "ラッパ"
          ["COUNT"]=>
          int(3)
        }
      }
    }
    
[/code]

これと同様の変換をを Python の `reduce()`（ないし別の方法）で行うことはできませんでしょうか。


CC BY-SA 3.0
2015-01-23T16:24:14.597
5171
2015-02-23T03:11:45.073
2015-01-24T07:44:48.307
30
3979
question
python
多次元配列テーブルデータを Python の reduce() を使って変換する方法について


reduceじゃないですが、defaultdictを使うといいんじゃないでしょうか。

[code]

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    from pprint import pprint as pp
    from collections import defaultdict
    
    lst = [{ "GROUP": "A", "NAME": u"りんご", "COUNT": 1 },
           { "GROUP": "A", "NAME": u"ゴリラ", "COUNT": 2 },
           { "GROUP": "B", "NAME": u"ラッパ", "COUNT": 3 },]
    
    convert_list = defaultdict(list)
    for row in lst:
        convert_list[row["GROUP"]].append(row)
    
    pp(dict(convert_list))
    
[/code]

結果:

[code]

    {'A': [{'COUNT': 1, 'GROUP': 'A', 'NAME': u'\u308a\u3093\u3054'},
           {'COUNT': 2, 'GROUP': 'A', 'NAME': u'\u30b4\u30ea\u30e9'}],
     'B': [{'COUNT': 3, 'GROUP': 'B', 'NAME': u'\u30e9\u30c3\u30d1'}]}
    
[/code]


CC BY-SA 3.0
2015-01-23T16:49:39.333
5172
2015-01-23T16:49:39.333
62
5171
answer


reduceを使う方法もご紹介します。

[code]

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import sys
    if sys.version_info[0] >= 3:
        from functools import reduce
    from pprint import pprint as pp
    
    lst = [{"GROUP": "A", "NAME": u"りんご", "COUNT": 1},
           {"GROUP": "A", "NAME": u"ゴリラ", "COUNT": 2},
           {"GROUP": "B", "NAME": u"ラッパ", "COUNT": 3}, ]
    
    def func(result, row):
        if not row["GROUP"] in result:
            result[row["GROUP"]] = []
    
        result[row["GROUP"]].append(row)
        return result
    
    pp(reduce(func, lst, {}))
    
[/code]

結果:

[code]

    {'A': [{'COUNT': 1, 'GROUP': 'A', 'NAME': 'りんご'},
           {'COUNT': 2, 'GROUP': 'A', 'NAME': 'ゴリラ'}],
     'B': [{'COUNT': 3, 'GROUP': 'B', 'NAME': 'ラッパ'}]}
    
[/code]

Pythonは複数行の無名関数が書けないので、一度関数(func)を定義しています。  
（関数を定義せずとも内包表記で記述できそうですが、可読性は低下すると思います）  
関数内での処理の流れは、ご質問のコードと同じです。

また、最初にPythonのバージョン確認と (python 3以上であれば) reduceをimportする処理をしています。これはPython
3.0以上ではreduceが組み込み関数ではなくfunctoolsモジュールに移動しているためです。結果はPython
3.4のものですが、2.7でも上記コードは実行可能です。


CC BY-SA 3.0
2015-01-23T23:44:19.897
5183
2015-01-23T23:44:19.897
3589
5171
answer


[cytoolz](https://github.com/pytoolz/cytoolz/)を使えば：

[code]

    from cytoolz import groupby
    lst = [{"GROUP": "A", "NAME": u"りんご", "COUNT": 1},
           {"GROUP": "A", "NAME": u"ゴリラ", "COUNT": 2},
           {"GROUP": "B", "NAME": u"ラッパ", "COUNT": 3}, ]
    groupby("GROUP", lst)
    
[/code]

出力は：

[code]

    {'A': [{'COUNT': 1, 'GROUP': 'A', 'NAME': u'\u308a\u3093\u3054'},
      {'COUNT': 2, 'GROUP': 'A', 'NAME': u'\u30b4\u30ea\u30e9'}],
     'B': [{'COUNT': 3, 'GROUP': 'B', 'NAME': u'\u30e9\u30c3\u30d1'}]}
    
[/code]


CC BY-SA 3.0
2015-02-23T03:11:45.073
6941
2015-02-23T03:11:45.073
8488
5171
answer