2016-10-03 116 views
0

我正在將JSON讀入我的腳本並構建一個由字典組成的列表。將字典附加到列表中時出現奇怪行爲

我的JSON:

{ 
    "JMF": { 
     "table1": { 
      "email": "[email protected]", 
      "guests": [ 
      "test1", 
      "test2" 
      ] 
     }, 
     "table2": { 
      "email": "[email protected]", 
      "guests": [ 
      "test3" 
      ] 
     } 
    }, 
    "JMC": { 
     "table3": { 
     "email": "[email protected]", 
     "guests": [ 
      "test11" 
     ] 
     } 
    }, 
    "JMD": { 
     "table4": { 
     "email": "[email protected]", 
     "guests": [ 
      "test12" 
     ] 
     }, 
     "table5": { 
     "email": "[email protected]", 
     "guests": [ 
      "test17" 
     ] 
     } 
    } 
} 

我的代碼:

def get_json(): 
    userinfo_list = [] 
    with open('guest_users.json') as json_file: 
     json_file = json.load(json_file) 
     keys = json_file.keys() 
     for key in keys: 
      userinfo = {} 
      for table_key in json_file[key].keys(): 
       email = json_file[key][table_key]['email'] 
       users_dict = {} 
       users_list = [] 
       for user in json_file[key][table_key]['guests']: 
        users_dict['username'] = user 
        users_dict['password'] = generate_password() 
        users_list.append(users_dict) 
       userinfo['company'] = key 
       userinfo['email'] = email 
       userinfo['userinfo'] = users_list 
       userinfo_list.append(userinfo) 
       print(userinfo) 
       print(userinfo_list) 

的問題是,我的JSON有兩個子鍵(table*)在userinfo_list價值得到儘快覆蓋。

這是輸出我得到的,這沒有任何意義:

{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}] 
{'userinfo': [{'username': 'test17', 'password': 'A8Jue5'}], 'email': '[email protected]', 'company': 'JMD'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test17', 'password': 'A8Jue5'}], 'email': '[email protected]', 'company': 'JMD'}] 
{'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}] 
{'userinfo': [{'username': 'test2', 'password': 'GagQ59'}, {'username': 'test2', 'password': 'GagQ59'}], 'email': '[email protected]', 'company': 'JMF'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test2', 'password': 'GagQ59'}, {'username': 'test2', 'password': 'GagQ59'}], 'email': '[email protected]', 'company': 'JMF'}] 
{'userinfo': [{'username': 'test3', 'password': 'U9gP0j'}], 'email': '[email protected]', 'company': 'JMF'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test3', 'password': 'U9gP0j'}], 'email': '[email protected]', 'company': 'JMF'}, {'userinfo': [{'username': 'test3', 'password': 'U9gP0j'}], 'email': '[email protected]', 'company': 'JMF'}] 
+0

不要覆蓋數據。總是嘗試創建新的列表,新的字典,新的一切 - 如果RAM內存允許你 - 並且它可以讓你在99%的情況下。 –

回答

2

您重新追加同一個字典每次迭代:

users_dict = {} # only one copy of this dictionary is ever created 
users_list = [] 
for user in json_file[key][table_key]['guests']: 
    users_dict['username'] = user 
    users_dict['password'] = generate_password() 
    users_list.append(users_dict) # appending a reference to users_dict 

追加不創建副本,因此您可以獲得對同一字典的多個引用,並且只會看到反映的最後更改。您在userinfo字典中犯了同樣的錯誤。

創建一個新的字典循環:

users_list = [] 
for user in json_file[key][table_key]['guests']: 
    users_dict = {} 
    users_dict['username'] = user 
    users_dict['password'] = generate_password() 
    users_list.append(users_dict) 

創建字典時,你可以直接指定鍵值對:

users_list = [] 
for user in json_file[key][table_key]['guests']: 
    users_dict = { 
     'username': user, 
     'password': generate_password() 
    } 
    users_list.append(users_dict) 

,這可以用一個簡化list comprehension至:

users_list = [{'username': user, 'password': generate_password()} 
       for user in json_file[key][table_key]['guests']] 

請注意,您無需撥打dict.keys()即可循環查看字典。您可以直接循環通過字典具有完全相同的結果。你可能要循環.items()代替,並避免查找關鍵每次的價值,並使用.values()當你實際上並不需要的關鍵都:

userinfo_list = [] 
for company, db in json_file.items(): 
    for table in db.values(): 
     userinfo = { 
      'company': company, 
      'email': table['email'], 
      'userinfo': [ 
       {'username': user, 'password': generate_password()} 
       for user in table['guests']] 
     } 
     userinfo_list.append(userinfo) 

每桌字典的創建每個公司也可以用列表理解取代,但是在這一點上堅持嵌套for循環可能會更容易理解未來的讀者。

上面現在生產:

[{'company': 'JMF', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test1'}, 
       {'password': 'random_password_really', 'username': 'test2'}]}, 
{'company': 'JMF', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test3'}]}, 
{'company': 'JMC', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test11'}]}, 
{'company': 'JMD', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test12'}]}, 
{'company': 'JMD', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test17'}]}] 

從樣本數據(和我自己的generate_password()定義)。

+0

這個工作完美,但我無法適應你的代碼到我更新的JSON。請參閱我的原始帖子以獲取更新的JSON。 – rhillhouse

+0

@ou_snaaksie:那通常是一個新問題。你需要在這裏過濾每個'db'字典的鍵:'對於tablename,db.items()中的表:'',如果不是tablename.startswith('table'):continue'(而不是當前的'for table在分貝。values():'loop)會跳過任何不以''table'開頭的鍵,比如''lang''。 –