簡體   English   中英

兩個字典python的笛卡爾乘積

[英]Cartesian Product for two dictionaries python

好的,所以我有兩個字典。

dictionary_1 = {'status': ['online', 'Away', 'Offline'],
                'Absent':['yes', 'no', 'half day']}
dictionary_2 = {'healthy': ['yes', 'no'],
                'insane': ['yes', 'no']

現在,我需要將它們結合起來,以便獲得帶有以下內容的新字典:

{'status': ['online', 'online', 'away', 'away', 'Offline', 'Offline'],
 'Absent': ['yes', 'yes', 'no', 'no', 'half day', 'half day'],
 'healthy': ['yes', 'no', 'yes', 'no', 'yes', 'no'],
 'insane': ['yes', 'no', 'yes', 'no', 'yes', 'no']
}

這是一個很晚的更新,但是如果有人感興趣,我找到了一種無需itertools的方法。

def cartesian_product(dict1, dict2):
    cartesian_dict = {}
    dict1_length = len(list(dict1.values())[0])
    dict2_length = len(list(dict2.values())[0])
    h = []
    for key in dict1:
        for value in dict1[key]:
            if not key in cartesian_dict:
                cartesian_dict[key] = []
                cartesian_dict[key].extend([value]*dict2_length)
            else:   
                cartesian_dict[key].extend([value]*dict2_length)
    for key in dict2:
        cartesian_dict[key] = dict2[key]*dict1_length
    return cartesian_dict

最佳猜測,基於@abarnert的解釋(並假設當前輸出中的healthyinsane值是錯誤的,因為它們只有四個成員):

d1 = {'status': ['online', 'Away', 'Offline'] ,'absent':['yes', 'no', 'half day']}
d2 = {'healthy': ['yes', 'no'], 'insane': ['yes', 'no']}
d1_columns = zip(*d1.values())
d2_columns = zip(*d2.values())
col_groups = [c1+c2 for c1, c2 in itertools.product(d1_columns, d2_columns)]
rows = zip(*col_groups)
combined_keys = list(d1) + list(d2)
d_combined = dict(zip(combined_keys, rows))

產生

>>> pprint.pprint(d_combined)
{'absent': ('yes', 'yes', 'no', 'no', 'half day', 'half day'),
 'healthy': ('yes', 'no', 'yes', 'no', 'yes', 'no'),
 'insane': ('yes', 'no', 'yes', 'no', 'yes', 'no'),
 'status': ('online', 'online', 'Away', 'Away', 'Offline', 'Offline')}

或者,按照您的訂單,

>>> order = ["status", "absent", "healthy", "insane"]
>>> for k in order:
    print k, d_combined[k]
...     
status ('online', 'online', 'Away', 'Away', 'Offline', 'Offline')
absent ('yes', 'yes', 'no', 'no', 'half day', 'half day')
healthy ('yes', 'no', 'yes', 'no', 'yes', 'no')
insane ('yes', 'no', 'yes', 'no', 'yes', 'no')

嘗試以下操作:它將兩個dict值組合在一起,進行乘積運算,然后將它們重新分離成一個dict。

import itertools

dictionary_1 = {'status': ['online', 'Away', 'Offline'],
                'Absent':['yes', 'no', 'half day']}
dictionary_2 = {'healthy': ['yes', 'no', 'recovering'],
                'insane': ['yes', 'no', 'partially' ]}

keys = dictionary_1.keys() + dictionary_2.keys()

first_values = zip(*dictionary_1.values())
# [('online','yes'), ('Away','no'),('Offline','half day')]

second_values = zip(*dictionary_2.values())

# this product will replicate the first_values 
# as many times as second_values exists
values_list = [i1+i2 for(i1,i2) in itertools.product(first_values,second_values)]

#re-separate the value lists for dict.
values = zip(*values_list)

new_dict = {key:list(values[i]) for i,key in enumerate(keys)}  

我在做測試用例之前遇到了這個問題。 我現在在pip上有一個名為“ looper”的程序包,它通過一些字典魔術和我發現有用的其他東西擴展了itertools。

https://pypi.python.org/pypi/looper

您想要的似乎不是兩個字典的完整笛卡爾積,該字典的長度為36個,將每個鍵d1 [k1] * d1 [k2] * d2 [k1] * d2 [k2]組合在一起。

相反,您似乎想要d1 [k1,k2] * d2 [k1,k2],為每個鍵均勻地遍歷n。 這被稱為zip函數,而dict_zip為字典執行此操作。

from pprint import pprint
from looper import iterutil

dict_1 = {'status':  ['online', 'Away', 'Offline'],
          'Absent':  ['yes', 'no', 'half day']}
dict_2 = {'healthy': ['yes', 'no'],
          'insane':  ['yes', 'no']}

# the first thing to do is to zip the dictionaries up. This produces a dictionary for each value of n in d[k][n]
zipped_dict_1 = iterutil.dict_zip(**dict_1)
# {'Absent': 'yes', 'status': 'online'}
# {'Absent': 'no', 'status': 'Away'}
# {'Absent': 'half day', 'status': 'Offline'}
zipped_dict_2 = iterutil.dict_zip(**dict_2)
# {'healthy': 'yes', 'insane': 'yes'}
# {'healthy': 'no', 'insane': 'no'}


# Now the output is a list of flattened dictionaries, take the Cartesian product of them.
product_dict = iterutil.product(zipped_dict_1,zipped_dict_2) 
# ({'Absent': 'yes', 'status': 'online'}, {'healthy': 'yes', 'insane': 'yes'})
# ({'Absent': 'yes', 'status': 'online'}, {'healthy': 'no', 'insane': 'no'})
# ({'Absent': 'no', 'status': 'Away'}, {'healthy': 'yes', 'insane': 'yes'})
# ({'Absent': 'no', 'status': 'Away'}, {'healthy': 'no', 'insane': 'no'})
# ({'Absent': 'half day', 'status': 'Offline'}, {'healthy': 'yes', 'insane': 'yes'})
# ({'Absent': 'half day', 'status': 'Offline'}, {'healthy': 'no', 'insane': 'no'})

# The product function produces tuples which must be combined in to a final dictionary.
# Merge the dictionaries using imap
merged_dict =  iterutil.imap(lambda x: dict(x[0].items()+x[1].items()),product_dict)

for d in merged_dict:
    pprint(d)

輸出值

{'Absent': 'yes', 'healthy': 'yes', 'insane': 'yes', 'status': 'online'}
{'Absent': 'yes', 'healthy': 'no', 'insane': 'no', 'status': 'online'}
{'Absent': 'no', 'healthy': 'yes', 'insane': 'yes', 'status': 'Away'}
{'Absent': 'no', 'healthy': 'no', 'insane': 'no', 'status': 'Away'}
{'Absent': 'half day', 'healthy': 'yes', 'insane': 'yes', 'status': 'Offline'}
{'Absent': 'half day', 'healthy': 'no', 'insane': 'no', 'status': 'Offline'}

我需要的是第一個字典重復第一個值第二個字典中值的次數

好的,因此您想將第二個字典中的值的郵政編碼與第一個字典中的每個值乘積,反之亦然。

為此,您將需要解壓縮兩個字典的值,乘積結果,解壓縮結果,然后使用對應原始字典中的鍵將結果2元組的每半壓縮,將鍵值對的兩個結果可迭代量展平合並成一個字典。 (您可以將值展平,並將其從兩個字典壓縮到展平的鍵上,但是我不確定這是否保證正確的順序…)

這聽起來像是一團糟,但這就是您要的。

將字典放入數組,然后執行以下操作:

dictionaries[dict_1,dict_2]

product = {}
arr = []
for d in dictionaries:
    for k in dictionaries[d]:
        arr.append(d.get(k))
        product[k] = None
for k in product:
    product[k] = arr

暫無
暫無

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

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