2008-10-09 52 views
2

他是一個尋找最多Pythonic解決方案的有趣問題。假設我有一個映射列表{'id': id, 'url': url}。列表中的某些id是重複的,我想創建一個新列表,刪除所有重複項。我想出了以下功能:從映射列表中提取唯一項目

def unique_mapping(map): 
    d = {} 
    for res in map: 
     d[res['id']] = res['url'] 

    return [{'id': id, 'url': d[id]} for id in d] 

我想這是非常有效的。但是有沒有「更多Pythonic」的方式?或者也許更有效的方法?

回答

4

您的示例可以稍微重寫,以使用生成器表達式構造第一個字典並刪除構建其他映射的必要性。只重用舊的:

def unique_mapping(mappings): 
    return dict((m['id'], m) for m in mappings).values() 

雖然這是一個單線程,但我仍然認爲它是非常可讀的。

還有你必須使用你原來的解決方案,我的時候要記住兩兩件事:

  • 的項目不會總是在他們原先
  • 後來的條目將覆蓋相同的順序返回先前使用相同ID的條目

如果您不介意,那麼我建議您使用上面的解決方案。在其他情況下,該功能保留順序和對待第一個遇到的IDS優先:

def unique_mapping(mappings): 
    addedIds = set() 
    for m in mappings: 
     mId = m['id'] 
     if mId not in addedIds: 
      addedIds.add(mId) 
      yield m 

您可能需要如果你需要一個列表,而不是一臺發電機與list(unique_mappings(mappings))調用它。

2

有幾件事情可以改進。

  • 你進行兩個循環,一個比原來的字典,然後再對結果字典。相反,您可以一步完成您的結果。

  • 您可以更改爲使用生成器,以避免預先構建整個列表。 (如果需要,使用列表(unique_mapping(items))轉換爲完整列表)

  • 當您只需檢查重複項時,不需要存儲該值,您可以使用集合。

  • 您正在爲每個元素重新創建字典,而不是返回原件。這實際上可能是需要的(例如,你正在修改它們,而不想觸摸原始的),但是如果不是,它會更有效地使用已經創建的字典。

下面是一個實現:

def unique_mapping(items): 
    s = set() 
    for res in items: 
     if res['id'] not in s: 
      yield res 
      s.add(res['id']) 
1

我認爲這是可以做簡單一些。字典不能容忍重複的密鑰。將映射列表映射到映射字典中。這將刪除重複項。

>>> someListOfDicts= [ 
    {'url': 'http://a', 'id': 'a'}, 
    {'url': 'http://b', 'id': 'b'}, 
    {'url': 'http://c', 'id': 'a'}] 

>>> dict([(x['id'],x) for x in someListOfDicts ]).values() 

[{'url': 'http://c', 'id': 'a'}, {'url': 'http://b', 'id': 'b'}]