同値類の素敵な表し方と、tuple/list/set

公開日:2018-10-18
最終更新:2018-10-24

この記事の目的

  • 同値類を優雅に、かつ利用しやすい形式で記述して、様々な分岐を効率よく処理したい
    • 人間が書く時に効率よく書ける
    • プログラムの処理効率がよい

という事について、あまり良い方法を思いつかなかったので、相談・議論したいのですが、全く何もしないのも勿体ないので、とりあえず超素朴なpythonの実装についてtuple/list/setで速度を比較します。

発端

元々の発端は、CSVのヘッダ項目の多言語対応でした。 例えば、メールアドレスというカラムとmail_addressというカラムを同一視したい。 あるいは、emailとかそういうのもあるかもしれないけど、それも同一視したい。

そのようなことを思っていて、取込処理においてファイルとDBカラムのマッピング(またはデータトランスファーオブジェクトとのマッピング)を円滑にしたいと思っています。

※equivalent → equivalence

素朴な回答

私が素朴に思いついた構造は、以下のようなものです。本当に素朴です。 以下、pythonで記します。

animal_equivalence_group = [
    ['dog', 'いぬ', '犬', 'わんちゃん'],
    ['cat', 'ねこ', '猫', 'パンダの熊抜き'],
    ['bird', 'とり', '鳥', 'こいつだけ範囲広い'],
    ['monkey', 'さる', '猿', 'ルフィ', '黄猿'],
    ['mouse', 'マウス', 'シリアルマウス', 'バスマウス'],
]

で、これを使って判定処理を書くと、以下のようになります。

def in_which_equivalence_group(element, equivalence_group):
    r = [g for g in equivalence_group if element in g]
    return r[0] if r else None

in_which_equivalence_group('パンダの熊抜き', animal_equivalence_group)

パフォーマンスについて(比較つき)

で、本質的にこれ以上良い(簡便な)表記を思いついていないのですが、とりあえずリストを使うと遅いという指摘を受けました。

確かにそれはそのとおり、tupleやsetを使うとどれぐらい変わるものなのか、試すことにしました。 このデータでだけ試しているので、カーディナリティ等によって結果が変化しうるという事を記した上で、比較をしてみます。

# tuple/list/setをためすよ!
from timeit import timeit

str_functions = {
    'tuple': lambda s: '(' + s + ')',
    'list': lambda s: '[' + s + ']',
    'set': lambda s: '{' + s + '}',
}

for (k_a, v_a), (k_b, v_b) in product(str_functions.items(), repeat=2):
    try:
        equiv_str= v_b(v_a('element for element in group') + ' for group in animal_equivalence_group')
        print(equiv_str)
        equiv = eval(equiv_str)
        timeit("in_which_equivalence_group('パンダの熊抜き', equiv)", globals=globals())
        print('----')
    except Exception as ex:
        print('# ' + str(ex))

実行結果は以下のようになりました。

((element for element in group) for group in animal_equivalence_group)
0.33937404499999957
----
[(element for element in group) for group in animal_equivalence_group]
0.5900618580000128
----
{(element for element in group) for group in animal_equivalence_group}
0.5903389540000035
----
([element for element in group] for group in animal_equivalence_group)
0.345817602000011
----
[[element for element in group] for group in animal_equivalence_group]
0.8542305559999477
----
{[element for element in group] for group in animal_equivalence_group}
# unhashable type: 'list'
({element for element in group} for group in animal_equivalence_group)
0.3468227040000329
----
[{element for element in group} for group in animal_equivalence_group]
0.6108999139999582
----
{{element for element in group} for group in animal_equivalence_group}
# unhashable type: 'set'

unhashableだから例外が出るのはそのとおりなのですが、この例の場合では両方tupleが一番早いですね。

さて

こういうの、どう書くのがいいんでしょうね…

その他のエモ

記事が少しでもいいなと思ったらクラップを送ってみよう!
18
+1
だべだべ - @sasanquaneufの技術ブログ

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする