简体   繁体   English

基于计数器增加Python字典值

[英]Incrementing Python Dictionary Value based on a Counter

I have a dictionary with duplicate values. 我有一个重复值的字典。

Deca_dict = {
    "1": "2_506",
    "2": "2_506",
    "3": "2_506",
    "4": "2_600",
    "5": "2_600",
    "6": "1_650"
}

I have used collections.Counter to count how many of each there are. 我已经使用了collections.Counter来计算每个中有多少个。

decaAdd_occurrences = {'2_506':3, '2_600':2, '1_650':1}

I then created a new dictionary of values to be updated. 然后我创建了一个要更新的新值字典。

deca_double_dict = {key: value for key, value in Deca_dict.items()
                        if decaAdd_occurrences[value] > 1}
deca_double_dict = {
    "1": "2_506",
    "3": "2_506",
    "2": "2_506",
    "4": "2_600"
}

(in this case, it's the original dict without the last item) (在这种情况下,它是没有最后一项的原始词典)

I'm trying to figure out how to increment num, for the values of counter_dict minus 1. This will update all the values except one, which can stay the same. 我试图弄清楚如何增加num,使counter_dict的值减去1.这将更新除了一个之外的所有值,它们可以保持不变。 The goal output allows one of the duplicates to keep the same value, whereas the rest will have the first number of the value string incremented increasingly (based on the number of duplicated counted). 目标输出允许其中一个副本保持相同的值,而其余的将使值字符串的第一个数字逐渐增加(基于重复计数的数量)。 I'm trying to achieve unique values for the data represented by the original Deca_dict. 我正在尝试为原始Deca_dict表示的数据实现唯一值。

Goal output = {'1':'3_506', '2':'4_506', '3':'2_506', '4':'3_600', '5':'2_600'}

I started going about things the following way, but ended up just incrementing all double items, resulting in what I had originally, except with values plus one. 我开始按照以下方式处理事情,但最终只是递增所有双项,导致我原来的,除了值加一。 For context: The values of the original Deca_dict were found concatenating two numbers (deca_address_num and deca_num_route). 对于上下文:发现原始Deca_dict的值连接两个数字(deca_address_num和deca_num_route)。 Also, homesLayer is a QGIS vector layer where deca_address_num and deca_num_route are stocked in fields with indices d_address_idx and id_route_idx. 此外,homesLayer是一个QGIS矢量图层,其中deca_address_num和deca_num_route存储在索引为d_address_idx和id_route_idx的字段中。

for key in deca_double_dict.keys():
    for home in homesLayer.getFeatures():
        if home.id() == key:
            deca_address_num = home.attributes()[d_address_idx]
            deca_num_route = home.attributes()[id_route_idx]
            deca_address_plus = deca_address_num + increment
            next_deca_address = (str(deca_address_plus) + '_' +
                                 str(deca_num_route))
            if not next_deca_address in Deca_dict.values():
                update_deca_dbl_dict[key] = next_deca_address

The result is useless: 结果没用:

Update_deca_dbl_dict = {
    "1": "3_506",
    "3": "3_506",
    "2": "3_506",
    "5": "3_600",
    "4": "3_600"
}

My second try attempts to include a counter, but things are in the wrong place. 我的第二次尝试试图包括一个柜台,但事情是在错误的地方。

for key, value in deca_double_dict.iteritems():
    iterations = decaAdd_occurrences[value] - 1
    for home in homesLayer.getFeatures():
        if home.id() == key:
            #deca_homeID_list.append(home.id())
            increment = 1
            deca_address_num = home.attributes()[d_address_idx]
            deca_num_route = home.attributes()[id_route_idx]
            deca_address_plus = deca_address_num + increment
            next_deca_address = (str(deca_address_plus) + '_' +
                                 str(deca_num_route))
            #print deca_num_route
            while iterations > 0:
                if not next_deca_address in Deca_dict.values():
                    update_deca_dbl_dict[key] = next_deca_address
                    iterations -= 1
                    increment += 1

UPDATE Even though one of the answers below works for incrementing all duplicate items of my dictionary, I am trying to re-work my code, as I need to have this comparison condition to the original data in order to increment. 更新即使下面的答案之一适用于递增我的字典的所有重复项目,我正在尝试重新处理我的代码,因为我需要将这个比较条件与原始数据进行递增。 I still have the same result as my first try (the useless one). 我仍然有与第一次尝试相同的结果(无用的)。

for key, value in deca_double_dict.iteritems():
    for home in homesLayer.getFeatures():
        if home.id() == key:
            iterations = decaAdd_occurrences[value] - 1
            increment = 1
            while iterations > 0:
                deca_address_num = home.attributes()[d_address_idx]
                deca_num_route = home.attributes()[id_route_idx]
                deca_address_plus = deca_address_num + increment
                current_address = str(deca_address_num) + '_' + str(deca_num_route)
                next_deca_address = (str(deca_address_plus) + '_' +
                                 str(deca_num_route))
                if not next_deca_address in Deca_dict.values():
                    update_deca_dbl_dict[key] = next_deca_address
                    iterations -= 1
                    increment += 1
                else:
                    alpha_deca_dbl_dict[key] = current_address
                    iterations = 0

Is this approximately what you want? 这大概是你想要的吗? I assume you can deal with the function to change 2_506 into 3_506 etc. Instead of your Counter, I use a set to insure that there are no duplicate values. 我假设您可以处理将2_506更改为3_506等的功能。而不是您的计数器,我使用一组来确保没有重复的值。

In the original post I cut off a line at the bottom, sorry. 在原帖中,我在底部剪了一条线,抱歉。

values_so_far = set()
d1 = {} # ---your original dictionary with duplicate values---
d2 = {} # d1 with all the duplicates changed
def increment_value(old_value):
    # you know how to write this
    # return the modified string

for k,v in d1.items():
    while v in values_so_far:
        v = increment_value(v)
    d2[k] = v
    values_so_far.add(v)

Here's a solution: Essentially, it keeps the first of the duplicate values and increments the prepended number on the rest of the duplicates. 这是一个解决方案:基本上,它保留第一个重复值,并在其余重复项上增加前置数字。

from collections import OrderedDict, defaultdict
orig_d = {'1':'2_506', '2':'2_506', '3':'2_506', '4':'2_600', '5':'2_600'}
orig_d = OrderedDict(sorted(orig_d.items(), key=lambda x: x[0]))

counter = defaultdict(int)
for k, v in orig_d.items():
    counter[v] += 1
    if counter[v] > 1:
        pre, post = v.split('_')
        pre = int(pre) + (counter[v] - 1)
        orig_d[k] = "%s_%s" % (pre, post)

print(orig_d)

Result: 结果:

OrderedDict([('1', '2_506'), ('2', '3_506'), ('3', '4_506'), ('4', '2_600'), ('5', '3_600')])

I think this does what you want. 我认为这样做你想要的。 I modified your input dictionary slightly to better illustrate what happens. 我稍微修改了你的输入字典,以更好地说明发生了什么 A primary difference with what you were doing is that decaAdd_occurrences , which is created from the Counter dictionary, keeps track of not only the counts, but also the value of the current address num prefix. 与您所做的主要区别在于,从Counter字典创建的decaAdd_occurrences不仅跟踪计数,还跟踪当前地址num前缀的值。 This makes it possible to know what the next num value to use is since both it and the count are updated during the process of modifying Deca_dict . 这使得可以知道要使用的下一个num值是什么,因为在修改Deca_dict的过程中它和计数都被更新。

from collections import Counter

Deca_dict = {
    "1": "2_506",
    "2": "2_506",
    "3": "2_506",
    "4": "2_600",
    "5": "1_650",
    "6": "2_600"
}

decaAdd_occurrences = {k: (int(k.split('_')[0]), v) for k,v in
                                Counter(Deca_dict.values()).items()}

for key, value in Deca_dict.items():
    num, cnt = decaAdd_occurrences[value]
    if cnt > 1:
        route = value.split('_')[1]
        next_num = num + 1
        Deca_dict[key] = '{}_{}'.format(next_num, route)
        decaAdd_occurrences[value] = next_num, cnt-1  # update values

Updated dictionary: 更新的字典:

Deca_dict -> {
    "1": "3_506",
    "2": "2_506",
    "3": "4_506",
    "4": "3_600",
    "5": "1_650",
    "6": "2_600"
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM