0

I am using Python.

Adding an integer to dictionary value in dictionary adds to all dictionaries in the dictionary.

def addQty(req_data, Cat):
    for item in req_data:
        state = item.get("state")
        sub_cat = item.get("sub_category")
        qty = item.get("quantity")
    
        if state in Cat:
            Cat[state][sub_cat] += int(qty)
    print(Cat)

The code adds to all dictionaries in the dictionary.

Dictionary Cat is created using:

def state_and_subcat(State, Subcat):
    Cat = State.copy()
    for state in StateSubCat:
       Cat[state] = Subcat
    return Cat

where State is built with {"state": state, "sub_category": subcat, "quantity": qty}

Using a deepcopy instead of .copy() does not seem to solve the problem.

An example of Cat is

{ "Alabama": { "Accessories": 2976, "Appliances": 1729, "Art": 3000, "Binders": 5974, "Bookcases": 868, "Chairs": 2356, "Copiers": 234, "Envelopes": 906, "Fasteners": 914, "Furnishings": 3563, "Labels": 1400, "Machines": 440, "Paper": 5178, "Phones": 3289, "Storage": 3158, "Supplies": 647, "Tables": 1241 }, "Arizona": { "Accessories": 2976, "Appliances": 1729, "Art": 3000, "Binders": 5974, "Bookcases": 868, "Chairs": 2356, "Copiers": 234, "Envelopes": 906, "Fasteners": 914, "Furnishings": 3563, "Labels": 1400, "Machines": 440, "Paper": 5178, "Phones": 3289, "Storage": 3158, "Supplies": 647, "Tables": 1241 }, "Arkansas": { "Accessories": 2976, "Appliances": 1729, "Art": 3000, "Binders": 5974, "Bookcases": 868, "Chairs": 2356, "Copiers": 234, "Envelopes": 906, "Fasteners": 914, "Furnishings": 3563, "Labels": 1400, "Machines": 440, "Paper": 5178, "Phones": 3289, "Storage": 3158, "Supplies": 647, "Tables": 1241 }, "California": { "Accessories": 2976, "Appliances": 1729, "Art": 3000, "Binders": 5974, "Bookcases": 868, "Chairs": 2356, "Copiers": 234, "Envelopes": 906, "Fasteners": 914, "Furnishings": 3563, "Labels": 1400, "Machines": 440, "Paper": 5178, "Phones": 3289, "Storage": 3158, "Supplies": 647, "Tables": 1241 }

An example of req_data is:

{ "quantity": "7", "state": "Arizona", "sub_category": "Storage" }, { "quantity": "2", "state": "California", "sub_category": "Chairs" }, { "quantity": "3", "state": "California", "sub_category": "Furnishings" }, { "quantity": "5", "state": "Ohio", "sub_category": "Phones" }, { "quantity": "2", "state": "Ohio", "sub_category": "Paper" }, { "quantity": "9", "state": "Ohio", "sub_category": "Fasteners" }, { "quantity": "3", "state": "California", "sub_category": "Paper" }, { "quantity": "1", "state": "California", "sub_category": "Paper" }, { "quantity": "4", "state": "California", "sub_category": "Art" }, { "quantity": "2", "state": "California", "sub_category": "Fasteners" }, { "quantity": "3", "state": "California", "sub_category": "Binders" }, { "quantity": "6", "state": "California", "sub_category": "Supplies" }, { "quantity": "14", "state": "California", "sub_category": "Furnishings" }, { "quantity": "2", "state": "Pennsylvania", "sub_category": "Furnishings" }, { "quantity": "3", "state": "California", "sub_category": "Art" }

How can I add to the specific qty to the sub_cat in the state only and not to all states?

Cedric
  • 1
  • 1
  • It looks like the problem is in the code that generates `Cat`, because your implementation of `addQty` should be fine. – Jasmijn Nov 29 '20 at 19:51
  • Welcome to SO! Check out the [tour] if you haven't already. For debugging help, please provide a [mre]. In this case it looks like the problem isn't even in the code you posted, but with how you're creating `Cat`. It looks like all the sub-dicts are the same object, not copies. – wjandrea Nov 29 '20 at 19:52
  • Does this answer your question? [Python: List of dictionary stores only last appended value in every iteration](https://stackoverflow.com/questions/46835197/python-list-of-dictionary-stores-only-last-appended-value-in-every-iteration) – wjandrea Nov 29 '20 at 19:56

2 Answers2

1

Because every element in Cat refers to the same object, the same object gets changed. This should fix it:

def state_and_subcat(State, Subcat):
    Cat = State.copy()
    for state in StateSubCat:
       Cat[state] = Subcat.copy()
    return Cat
Jasmijn
  • 9,370
  • 2
  • 29
  • 43
0

IIUC, you have a dictionary that holds multiple states and each state contains some list of quantities for items (Storage, Chairs etc).

From a list of dictionaries (each with a state, item and a quantity), you want to take the quantity and add it to the master dictionary for that state and item.

Here is a function and list comprehension that together should do what you are trying to do as well.

  1. add_new_quantity(): This function gets the k=state, i=sub_category, j=quantity from the master, and then returns a new quantity by adding to j, if it finds it in the req_data. If a new quantity is not found it just returns the original j.

  2. List comprehension: This iterates over the master list returning it in exactly the same form it is in. But, it simply replaces the quantity with the above function. The original unaltered master iterator is simply - {k:{i:j for i,j in v.items()} for k,v in d.items()}. This will simply return the original master, BUT after iteration through every key value that exists in it. I simply replace the j with the above function, which returns a new number if it finds the same state, sub_category in req_data, else it returns j's original value.

#Assuming this is a list of dictionaries.

req_data = [{'quantity': '7', 'state': 'Arizona', 'sub_category': 'Storage'},
 {'quantity': '2', 'state': 'California', 'sub_category': 'Chairs'},
 {'quantity': '3', 'state': 'California', 'sub_category': 'Furnishings'},
 {'quantity': '5', 'state': 'Ohio', 'sub_category': 'Phones'},
 {'quantity': '2', 'state': 'Ohio', 'sub_category': 'Paper'},
 {'quantity': '9', 'state': 'Ohio', 'sub_category': 'Fasteners'},
 {'quantity': '3', 'state': 'California', 'sub_category': 'Paper'},
 {'quantity': '1', 'state': 'California', 'sub_category': 'Paper'},
 {'quantity': '4', 'state': 'California', 'sub_category': 'Art'},
 {'quantity': '2', 'state': 'California', 'sub_category': 'Fasteners'},
 {'quantity': '3', 'state': 'California', 'sub_category': 'Binders'},
 {'quantity': '6', 'state': 'California', 'sub_category': 'Supplies'},
 {'quantity': '14', 'state': 'California', 'sub_category': 'Furnishings'},
 {'quantity': '2', 'state': 'Pennsylvania', 'sub_category': 'Furnishings'},
 {'quantity': '3', 'state': 'California', 'sub_category': 'Art'}]
#return original+new quantity if found in req_data
def add_new_quantity(k, i, j, data=req_data):
    new_subs = [r for r in req_data if r['state']==k and r['sub_category']==i]
    try: return j+int(new_subs[0]['quantity'])
    except: return j

#iterate over the master dictionary and update/ignore quantity values
new_master = {k:{i:add_new_quantity(k,i,j) for i,j in v.items()} for k,v in master.items()}
print(new_master)
#updated master dictionary
{'Alabama': {'Accessories': 2976,
  'Appliances': 1729,
  'Art': 3000,
  'Binders': 5974,
  'Bookcases': 868,
  'Chairs': 2356,
  'Copiers': 234,
  'Envelopes': 906,
  'Fasteners': 914,
  'Furnishings': 3563,
  'Labels': 1400,
  'Machines': 440,
  'Paper': 5178,
  'Phones': 3289,
  'Storage': 3158,
  'Supplies': 647,
  'Tables': 1241},
 'Arizona': {'Accessories': 2976,
  'Appliances': 1729,
  'Art': 3000,
  'Binders': 5974,
  'Bookcases': 868,
  'Chairs': 2356,
  'Copiers': 234,
  'Envelopes': 906,
  'Fasteners': 914,
  'Furnishings': 3563,
  'Labels': 1400,
  'Machines': 440,
  'Paper': 5178,
  'Phones': 3289,
  'Storage': 3165,
  'Supplies': 647,
  'Tables': 1241},
 'Arkansas': {'Accessories': 2976,
  'Appliances': 1729,
  'Art': 3000,
  'Binders': 5974,
  'Bookcases': 868,
  'Chairs': 2356,
  'Copiers': 234,
  'Envelopes': 906,
  'Fasteners': 914,
  'Furnishings': 3563,
  'Labels': 1400,
  'Machines': 440,
  'Paper': 5178,
  'Phones': 3289,
  'Storage': 3158,
  'Supplies': 647,
  'Tables': 1241},
 'California': {'Accessories': 2976,
  'Appliances': 1729,
  'Art': 3004,
  'Binders': 5977,
  'Bookcases': 868,
  'Chairs': 2358,
  'Copiers': 234,
  'Envelopes': 906,
  'Fasteners': 916,
  'Furnishings': 3566,
  'Labels': 1400,
  'Machines': 440,
  'Paper': 5181,
  'Phones': 3289,
  'Storage': 3158,
  'Supplies': 653,
  'Tables': 1241}}

PS. I used the variable name master instead of Cat, feel free to change that as you like.

Akshay Sehgal
  • 18,741
  • 3
  • 21
  • 51