Python社区  »  Python

python:按键(元组)将字典拆分为更小的字典

Jaood • 1 周前 • 10 次点击  

我有一本字典,其中的键是两个整数的元组 (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) 独自一人。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40247
 
10 次点击  
分享到微博
文章 [ 4 ]  |  最新文章 1 周前
Rick Teachey
Reply   •   1 楼
Rick Teachey    9 月前

这种方法对我来说似乎很简单,但肯定不是最快的:

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:])}

同样,这将是低效的。每一本新字典都要重复一次。但对于小问题,这应该是好的。

rajendra
Reply   •   2 楼
rajendra    9 月前

这应该管用。

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'}}
user2263572
Reply   •   3 楼
user2263572    9 月前

当然这可以写得更好,但你应该明白。只需遍历dict,并根据可以动态定义或生成的各种条件检查键的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)
jpp
Reply   •   4 楼
jpp    9 月前

你可以使用 collections.defaultdict ,迭代和更新由bucket边界确定的键。这比创建可变数量的变量更好。

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 按顺序。