我有一本字典,其中的键是两个整数(x,y)
的元组,值是字符串。
如何将字典拆分成较小的字典,其中的拆分取决于y
值是否大于某个阈值?
例如,说我有键(字典的值无关紧要,因此在此省略)
(0, 2), (0, 4), (0, 10), (0, 3), (0, 11), (0, 20), (0, 8), (0, 14)
并说我拥有0, 5, 10, 15
的门槛。
然后,一个拆分应该由具有以下键的字典组成:
(0,2), (0,4), (0,3)
因为y值均大于0,但不大于5。
然后下一个字典应该有键
(0,8)
因为它大于0和5,但不大于10。
然后我们有(0, 10), (0, 11), (0, 14)
因为它大于(或等于)0、5、10,但不等于15。
最后,我们本身就有(0, 20)
。
答案 0 :(得分:1)
您可以使用collections.defaultdict
来迭代和更新由存储桶边界确定的密钥。这比创建可变数量的变量更好。
d = {(0, 2): 1, (0, 4): 2, (0, 10): 3, (0, 3): 4,
(0, 11): 5, (0, 20): 6, (0, 8): 7, (0, 14): 8}
L = [0, 5, 10, 15, float('inf')] # include infinite to facilitate later comparisons
from collections import defaultdict
dd = defaultdict(dict)
for k, v in d.items():
for i, j in zip(L, L[1:]):
if i <= k[1] < j:
dd[i].update({k: v})
break
print(dd)
defaultdict(dict,
{0: {(0, 2): 1, (0, 3): 4, (0, 4): 2},
5: {(0, 8): 7},
10: {(0, 10): 3, (0, 11): 5, (0, 14): 8},
15: {(0, 20): 6}})
可以通过使用bisect
来改进算法,而不必依次迭代L
中的边界。
答案 1 :(得分:0)
当然,这可以写得更好,但是您应该明白这一点。只需遍历字典,然后根据可定义或动态生成的各种条件检查键的y值。
thing = {
(1,2): 'a',
(2,19): 'b'
}
d1 = {}
d2 = {}
for k, v in thing.items():
// while iterating through the original dict, write some logic to determine how you want to split up based on the y values.
if k[1] < 5:
d1[k] = v
if k[1] < 10:
d2[k] = v
print(d1, d2)
答案 2 :(得分:0)
这应该有效。
original_dict = {(0, 2):"a", (0, 4):"b", (0, 10):"c",
(0, 3):"d", (0, 11):"e", (0, 20):"f", (0, 8):"g", (0, 14):"h"}
thresholds = [0, 5, 10, 15]
thresholds = sorted(thresholds,reverse=True)
new_dict_of_dicts = {} #threshold: dict
for threshold in thresholds:
new_dict_of_dicts[threshold] = {}
for key in list(original_dict.keys()):
if key[1] > threshold:
new_dict_of_dicts[threshold][key] = original_dict.pop(key)
print(new_dict_of_dicts)
#{15: {(0, 20): 'f'}, 10: {(0, 11): 'e', (0, 14): 'h'}, 5: {(0, 10): 'c', (0, 8): 'g'}, 0: {(0, 2): 'a', (0, 4): 'b', (0, 3): 'd'}}
答案 3 :(得分:0)
这种方法对我来说似乎最简单,尽管它肯定不是最快的方法:
d1 = {(k1,k2):v for (k1,k2),v in d.items() if 0<k2<=5}
d2 = {(k1,k2):v for (k1,k2),v in d.items() if 5<k2<=10}
d3 = {(k1,k2):v for (k1,k2),v in d.items() if 10<k2<=15}
d4 = {(k1,k2):v for (k1,k2),v in d.items() if 15<k2}
或者像这样组合:
bounds = 0, 5, 10, 15, 1_000_000
bounds_dicts = {(b1,b2):{(k1,k2):v for (k1,k2),v in d.items() if b1<k2<=b2}
for (b1,b2) in zip(bounds[:-1],bounds[1:])}
同样,这将是低效率的。该字典将为每个新字典进行一次迭代。但是对于小问题,这应该没问题。