破棄されたブログ

このブログは破棄されました。

Collection Pipeline in Python

martinfowler.com でコレクションパイプラインという記事が上がってきたので、サンプルコードを Python で書いた。

TL;DR

Python の場合、 Ruby のようにメソッドチェーンで繋げないので、右下に伸びてきてツラい

データ

data = [
    {
        "title": "NoDBA",
        "words": 561,
        "tags": ["nosql", "people", "orm"],
        "type": "bliki",
    },
    {
        "title": "Infodeck",
        "words": 1145,
        "tags": ["nosql", "writing"],
        "type": "bliki",
    },
    {
        "title": "OrmHate",
        "words": 1718,
        "tags": ["nosql", "orm"],
        "type": "bliki",
    },
    {
        "title": "ruby",
        "words": 1313,
        "tags": ["ruby"],
        "type": "article",
    },
    {
        "title": "DDD_Aggregate",
        "words": 482,
        "tags": ["nosql", "ddd"],
        "type": "bliki",
    },
]

nosql タグを含むレコードを words 順でソートして上位 3 つをとる

islice(sorted(filter(lambda d: "nosql" in d.get("tags"),
                     data),
              key=lambda d: d.get("words")),
        0, 3)

総単語数を集計する

reduce を使って左畳み込みをする。初期アキュムレータが設定される仕組みはよくわからん。

reduce(operator.add,
       map(lambda d: d.get("words"),
           data))

各記事の種別を集計する

Python の groupby は、keyfunc で、第二引数で与えられた keyfunc(v) でグルーピングしたサブイテレータを返すので、 Rubygroup_by とは違う。 SQLGROUP BY とも異なり、イテレータ全体を見てグルーピングするわけではないので、予めソートする必要がある。

groups = groupby(sorted(data,
                        key=lambda d: d.get("type")),
                 lambda d: d.get("type"))

dict(starmap(lambda k, v: (k, sum(1 for _ in v)),
             groups))

各タグの単語数と記事数を集計する

だいぶ酷いことになった。もっといい方法があるかもしれない。

starmap(lambda k, v: (k, { "articles": len(v), "words": reduce(operator.add,
                                                               map(lambda d: d[1].get("words"),
                                                                   v)) }),
        starmap(lambda k, v: (k, list(v)),
            groupby(sorted(chain.from_iterable(map(lambda d: map(lambda tag: (tag, d),
                                                                 d.get("tags")),
                                                   data)),
                           key=lambda d: d[0]),
                    lambda d: d[0])))

感想

関数型の知見が足りてない

広告を非表示にする