[解決済み] ネストされた辞書やリスト内のキーの出現回数をすべて検索する
質問
このような辞書があります。
{ "id" : "abcde",
"key1" : "blah",
"key2" : "blah blah",
"nestedlist" : [
{ "id" : "qwerty",
"nestednestedlist" : [
{ "id" : "xyz",
"keyA" : "blah blah blah" },
{ "id" : "fghi",
"keyZ" : "blah blah blah" }],
"anothernestednestedlist" : [
{ "id" : "asdf",
"keyQ" : "blah blah" },
{ "id" : "yuiop",
"keyW" : "blah" }] } ] }
基本的には、任意の深さのリスト、辞書、文字列がネストされた辞書です。
すべての "id" キーの値を抽出するためにこれをトラバースする最良の方法は何でしょうか?私は、"//id" のような XPath クエリと同等のものを実現したいのです。id"の値は、常に文字列です。
だから、私の例から、私が必要とする出力は基本的にあります。
["abcde", "qwerty", "xyz", "fghi", "asdf", "yuiop"]
順番は重要ではありません。
どのように解決するのですか?
このQ/Aは、同じ問題に対していくつかの異なる解決策を提供しているので、非常に興味深いものでした。私はこれらの関数をすべて受け取り、複雑な辞書オブジェクトでそれらをテストしました。2 つの関数をテストから外さなければなりませんでした。なぜなら、失敗結果が多すぎたことと、リストまたはディクショナリーを値として返すことをサポートしていなかったからです。 どんな のデータに対して準備される必要があるからです。
そこで、私は他の関数を100.000回繰り返して
timeit
モジュールに100,000回出力してみたところ、以下のような結果になりました。
0.11 usec/pass on gen_dict_extract(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6.03 usec/pass on find_all_items(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.15 usec/pass on findkeys(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1.79 usec/pass on get_recursively(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.14 usec/pass on find(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.36 usec/pass on dict_extract(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
すべての関数は、検索する針が同じ('logging')で、辞書オブジェクトも同じで、このように構成されていました。
o = { 'temparature': '50',
'logging': {
'handlers': {
'console': {
'formatter': 'simple',
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
'level': 'DEBUG'
}
},
'loggers': {
'simpleExample': {
'handlers': ['console'],
'propagate': 'no',
'level': 'INFO'
},
'root': {
'handlers': ['console'],
'level': 'DEBUG'
}
},
'version': '1',
'formatters': {
'simple': {
'datefmt': "'%Y-%m-%d %H:%M:%S'",
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
}
}
},
'treatment': {'second': 5, 'last': 4, 'first': 4},
'treatment_plan': [[4, 5, 4], [4, 5, 4], [5, 5, 5]]
}
どの関数も同じ結果を出しましたが、時間差は劇的です この関数は
gen_dict_extract(k,o)
は、ここで紹介されている関数を参考にしたもので、実際のところ、この関数は
find
関数とほぼ同じですが、主な違いは、再帰中に文字列が渡された場合に備えて、与えられたオブジェクトが iteritems 関数を持っているかどうかをチェックしている点です。
def gen_dict_extract(key, var):
if hasattr(var,'iteritems'):
for k, v in var.iteritems():
if k == key:
yield v
if isinstance(v, dict):
for result in gen_dict_extract(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in gen_dict_extract(key, d):
yield result
つまり、この変形はここにある関数の中で最も高速で安全なものです。そして
find_all_items
は信じられないほど遅く、2 番目に遅い
get_recursivley
を除き、残りは
dict_extract
を除く残りの部分は互いに接近している。関数
fun
と
keyHole
は、文字列を探す場合のみ機能します。
興味深い学習面ですね :)
関連
-
[解決済み] リストにおけるdel、remove、popの違いについて
-
[解決済み] リストとタプルの違いは何ですか?
-
[解決済み] ある部分文字列のすべての出現箇所を見つけるにはどうすればよいですか?
-
[解決済み] ネストされた2つのリストの交点を求めるには?
-
[解決済み] ネストされた辞書をきれいに印刷するには?
-
[解決済み】Pythonでディレクトリ内の拡張子.txtのファイルをすべて検索する
-
[解決済み] Pandasの'Freq'タグにはどのような値が有効ですか?
-
[解決済み] PySparkでデータフレームのカラムをString型からDouble型に変更する方法は?
-
[解決済み] Pythonの文字列書式をリストで使う
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] PythonでファイルのMD5チェックサムを計算するには?重複
-
[解決済み] pandasのDataFrameから空のセルを含む行を削除する
-
[解決済み] django.db.migrations.exceptions.InconsistentMigrationHistory
-
[解決済み] Django Rest Framework ファイルアップロード
-
[解決済み] Pythonで0xを使わずにhex()を使うには?
-
[解決済み] あるオブジェクトが数であるかどうかを確認する、最もパイソン的な方法は何でしょうか?
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] Python Logging でログメッセージが2回表示される件
-
[解決済み] matplotlib でプロットの軸、目盛、ラベルの色を変更する方法
-
[解決済み] Pythonでランダムなファイル名を生成する最良の方法