2013-05-10 25 views
1

我不知道我用這個合適的術語---我可以稱之爲合併操作?簡單的匹配?在Python中做對應替換操作的更快方法?

我有兩本詞典。其中一個包含標籤ID列表。另一個是標籤ID和標籤ID名稱之間的對應關係。我想匹配ID並在第一個字典中包含標籤名稱。

因此,首先字典是這樣的:

>>> myjson 
[ 
{"tags" : ["1","3"],"otherdata" : "blah"}, 
{"tags" : ["2","4"],"otherdata" : "blah blah"} 
] 

二字典是這樣的:

>>> tagnames 
[ 
{"id": "1", "name":"bassoon"}, 
{"id": "2", "name":"banjo"}, 
{"id": "3", "name":"paw paw"}, 
{"id": "4", "name":"foxes"} 
] 

要與標籤ID名稱替換myjson標籤ID,我目前做這:

data = [] 
for j in myjson: 
    d = j 
    d['tagnames'] = [i['name'] for i in tagnames for y in d['tags'] if y==i['id']] 
    data.append(d) 

我所需的輸出是這樣的:

>>> data 
[ 
{"tags" : ["1","3"],"otherdata" : "blah", "tagname" : ["bassoon","paw paw"]}, 
{"tags" : ["2","4"],"otherdata" : "blah blah", "tagname": ["banjo","foxes"]} 
] 

我得到正確的輸出,但它似乎很慢。我知道它每次都在對myjson中的每個元素進行完整迭代x標記名中的每個元素的全部迭代(是mxn?nxn?),而且這樣做會很慢,但也許會有更聰明的語法或技巧來加速它?只走陣列一次而不是n次?

如果有人可以建議一種方法來完成這個任務,使用一個漂亮的地圖或功能方法而不是外部forloop,那麼Oooh也會很酷。

+1

'd [ '標記名']'已經改變了'myjson'結構*中的*。沒有必要創建一個新的數據列表。 'd = j'只是指定一個引用,字典是**不**複製的。 – 2013-05-10 14:15:27

+0

哇,真的嗎?讓人驚訝。好的,那應該開始加速,但是我擔心我會搞亂我的舊數據。 – Mittenchops 2013-05-10 14:19:03

回答

2

你想你的標記名列表轉變成一個字典:

tagnames_map = {t['id']: t['name'] for t in tagnames} 

現在,你可以找到更快的匹配標記名;你的代碼已經只是做原地的變化,所以我要把它簡化爲:

for d in myjson: 
    d['tagnames'] = [tagnames_map[t] for t in tagnames_map.viewkeys() & d['tags']] 

dict.viewkeys() method回報dictionary view object其作用就像一組。我們將該集合與您的標籤列表相交,產生一系列標籤,這些標籤都在tagnames_map中列出。通過這樣做,我們不必擔心地圖中缺少任何標籤。

如果您使用Python 3,那麼您只需直接使用tagnames_map.keys();在Python 3中,.keys(),.values()items()方法已更改爲始終返回字典視圖對象。

如果你想使一個副本,而不是,可能會使用d.copy()

data = [] 
for d in myjson: 
    d = d.copy() 
    d['tagnames'] = [tagnames_map[t] for t in tagnames_map.viewkeys() & d['tags']] 
    data.append(d) 

dict.copy()創建一個淺表副本;可變值不會被複制,新的字典只會引用相同的值。因爲你在這裏沒有改變價值,所以很好。

運行此對您的樣本輸入給:

>>> pprint(data) 
[{'otherdata': 'blah', 'tagnames': ['bassoon', 'paw paw'], 'tags': ['1', '3']}, 
{'otherdata': 'blah blah', 
    'tagnames': ['banjo', 'foxes'], 
    'tags': ['2', '4']}] 
+0

這是超級有用,非常清楚。我開始運行這個程序,並且對於我的實際示例,它仍然非常慢 - 但我確定比我的原始版本要快得多,甚至在我的實際示例中都沒有完成。這裏的緩慢只是野獸的性質? – Mittenchops 2013-05-10 14:35:06

+0

@Mittenchops:如果你的輸入數據集是巨大的,那麼是的,慢度是你輸入的數據量的函數。但是'標記名'的生成是局部快速的(O(N))而不是O(MN ),每個條目中'標籤'列表的長度爲'N','標籤名'列表的長度'M')。 – 2013-05-10 14:42:02

+0

@Mittenchops:如果您可以避免製作所有條目的副本,那還是更好。 – 2013-05-10 14:42:44

相關問題