4

私は次のような辞書を持っています:

{
   "checksum": "b884cbfb1a6697fa9b9eea9cb2054183",
   "roots": {
      "bookmark_bar": {
         "children": [ {
            "date_added": "12989159740428363",
            "id": "4",
            "name": "test2",
            "type": "url",
            "url": "chrome://bookmarks/#1"
         } ],
         "date_added": "12989159700896551",
         "date_modified": "12989159740428363",
         "id": "1",
         "name": "bookmark_bar",
         "type": "folder"
      },
      "other": {
         "children": [ {
            "date_added": "12989159740428363",
            "id": "4",
            "name": "test",
            "type": "url",
            "url": "chrome://bookmarks/#1"
         } ],
         "date_added": "12989159700896557",
         "date_modified": "0",
         "id": "2",
         "name": "aaa",
         "type": "folder"
      },
      "synced": {
         "children": [  ],
         "date_added": "12989159700896558",
         "date_modified": "0",
         "id": "3",
         "name": "bbb",
         "type": "folder"
      }
   },
   "version": 1
}

すべてが「roots」から始まります。URLとフォルダの2種類のデータがあり、それらは辞書です。フォルダの場合は、キー「children」が必要です。キーの値はリストです。さらに多くのURLとフォルダをその中に入れることができます。

ここで、このネストされた辞書をトラバースして、すべてのサブフォルダーのURLを取得したいので、次の関数を作成しました。

def traverse(dic):
    for i in dic:
        if i['type'] == 'folder':
            for j in traverse(i['children']):
                yield j
        elif i['type'] == 'url':
            yield i

そして私はそれをそのように使うことができます:

traverse(dictionary['roots']['bookmark_bar']['children'])

それは完璧に動作します。しかし、それはURLの辞書を生成するだけで、どこにあるのかわかりません。私も道を知りたいです。どうすればいいですか?

4

2 に答える 2

8

私はあなたとは少し異なるユースケースを持っていました。データベースに保存するために、クライアント設定を表す可変深度のJSON構造をキーと値のペアにフラット化する必要がありました。jsbuenoの答えを機能させることができませんでした。また、子を明示的にリストしたり封じ込めたりせずにケースを処理できるものが必要だったため、ニーズに合わせて変更しました。

def traverse(dic, path=None):
    if not path:
        path=[]
    if isinstance(dic,dict):
        for x in dic.keys():
            local_path = path[:]
            local_path.append(x)
            for b in traverse(dic[x], local_path):
                 yield b
    else: 
        yield path,dic

最終結果は、このようなJSON文字列を(可変の深さで)スクリプトに渡すことができ、ネストされたdictに変換します。

{
  "servers": {
    "uat": {
      "pkey": true,
      "user": "testval",
      "pass": true
    },
    "dev": {
      "pkey": true,
      "user": "testval",
      "pass": true
    }
  }
}

上記のジェネレーターを実行すると、次のようにきれいに印刷されるリストが作成されます。

([u'servers', u'uat', u'pkey'], True)
([u'servers', u'uat', u'user'], u'testval')
([u'servers', u'uat', u'pass'], True)
([u'servers', u'dev', u'pkey'], True)
([u'servers', u'dev', u'user'], u'testval')
([u'servers', u'dev', u'pass'], True)

これは、次のようなものを使用します:

for x in traverse(outobj):
    pprint(('.'.join(x[0]),x[1]))

次に、次のように、キーと値のペアの形式に変換できます。

(u'servers.uat.pkey', True)
(u'servers.uat.user', u'testval')
(u'servers.uat.pass', True)
(u'servers.dev.pkey', True)
(u'servers.dev.user', u'testval')
(u'servers.dev.pass', True)

受け入れられた回答が受け入れられた後、この方法で投稿していることは知っていますが、受け入れられた回答がうまくいかなかったため、構造にとらわれないこのバージョンが他の誰かを助けるかもしれません!

于 2015-08-13T21:44:00.837 に答える
1

私があなたが望むものを手に入れたかどうかはわかりませんが、あなたはこれをしたいかもしれません:

def traverse(dic, path=None):
    if not path:
        path = []
    for i in dic:
        local_path = path[:].append(i)
        if i['type'] == 'folder':
            for j in traverse(i['children'], local_path):
                yield j, local_path
        elif i['type'] == 'url':
            yield i, local_path

これで、関数はアイテムと、特定の場所にあるアイテムに到達するためのキーのシーケンスを生成します。

于 2012-08-13T12:47:55.030 に答える