簡體   English   中英

按多個值過濾字典

[英]Filtering a dictionary by multiple values

我是Python的新手,我很難制定一種過濾字典的“pythony”方法。

我有一個字典,看起來像這樣:

'217': {'586': 2.0, '578': 5.0, '172': 1.0, '1222': 1.0, '597': 4.0, '1303': 2.0, '195': 5.0, ...}
'660': {'176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0, '797': 4.0, '541': 3.0, '27': 1.0, '210': 4.0, ...}

等等。

然后我有一個字符串列表:

['2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39', ...]

我想要實現的是一個過濾字典,其中只存在字符串列表中包含任何值的元組。 我已經設法做到這一點,但只使用一個字符串作為一個要求,它看起來像這樣:

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if my_list[0] in v}

但是,如果我刪除[0],我會收到以下錯誤:

TypeError:不可用類型:'list'以下是一些預期的輸出值:

'115 : {'174': 4.0, '172': 4.0, '27': 3.0, '183': 5.0, '180': 3.0, '1039': 5.0, ... }

'212' : {'4': 3.0, '473': 4.0, '208': 5.0, '123': 4.0, '476': 3.0, '474': 4.0, ...}

正如您所看到的,第一個元組中的第三個值在其中為“27”,位於my_list中。 第二個元組中的第一個值的值為'4',也在my_list中。

我非常感謝任何形式的幫助。

謝謝!

你可以使用一個集合,如果值與集合不相交,則保持對:

st = {'2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39'}

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)}

如果他們不共享至少一個元素,他們將只是脫節:

In [6]: st ={1,2,3}

In [7]: v = [1,4,5]

In [8]: st.isdisjoint(v)
Out[8]: False

In [11]: v = [7,4,5]

In [12]: st.isdisjoint(v)
Out[12]: True

它有點相當於:

st = {'2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39'}

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if any(val in st for val in v)}

如果v中的任何元素在集合中,我們保留元素。

最糟糕的情況是我們檢查len(v)元素對集合,迭代mylist元素並檢查x是否在v中是每個case的O(len(my_list))並且還創建相同的k,v每次你得到一個配對比賽。

如果我們添加一個帶有更多匹配鍵的dict並將這些對添加到列表中,您可以看到會發生什么:

In [22]: my_list  = ['2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39']

In [23]: my_dict = {'217': {'586': 2.0, '578': 5.0, '172': 1.0, '1222': 1.0, '597': 4.0, '1303': 2.0, '195': 5.0},
   ....:            '660': {'176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0, '797': 4.0, '541': 3.0, '27': 1.0, '210': 4.0},
   ....:            '661': {'2': 4.0, '4': 3.0, '29': 5.0, '17': 4.0, '39': 4.0, '541': 3.0, '27': 1.0, '210': 4.0}}


In [24]: print [(k,v) for k,v in my_dict.iteritems() for x in my_list if x in v]
[('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('660', {'797': 4.0, '27': 1.0, '541': 3.0, '210': 4.0, '176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0})]

因為有7個匹配,我們得到相同的七次配對,你不會在dict中得到dupes,但你必須迭代len(my_list)次並x in v創建x in v的配對長度為True時間。 隨着my_list的長度增加,運行時間將相應增加。

僅僅使my_list 1000元素存在相當大的差異:

In [35]: len(my_list)
Out[35]: 1000

In [36]: %%timeit
   ....: st = set(my_list)
   ....: {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)}
   ....: 
10000 loops, best of 3: 21.9 µs per loop
In [37]: timeit {k:v for k,v in my_dict.iteritems() for x in my_list if x in v}
10000 loops, best of 3: 136 µs per loop

幾乎所有的時間花在集合創建上,如果你從一開始就使用一個集合,它運行速度快100倍:

In [40]: timeit {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)}

1000000 loops, best of 3: 1.09 µs per loop

如果我正確理解你的問題,你需要遍歷列表mylist並將每個元素與字典mydict值進行mydict

{k:v for k,v in mydict.iteritems() for x in mylist if x in v}

1)k:v for k,v in mydict.iteritems()是按對方迭代字典對。

2)用於MYLIST X如果x在V是迭代MYLIST並檢查MYLIST元件是否in內部字典V,因此檢查x in v等於檢查x in v.keys()其中x v中的鍵

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM