简体   繁体   中英

Subtract dictionary value from key

I have a dictionary like this:

a = {(8, 9): [[0, 0], [4, 5]], (3, 4): [[1, 2], [6, 7]]}

I would like to subtract the sum of the corresponding elements of the nested lists in the values from each element of each key, and replace the key with the result.

For example:

new_key[0] = 8 - 0+4 = 4, new_key[1] = 9 - (0+5) = 4

Hence the new key becomes (4, 4) and it replaces (8, 9)

I am not able to understand how to access a list of lists which is the value to the key!

Any ideas as to how to do this?

See Access item in a list of lists for indexing list of list.

For your specific case, this should work

b = {(k[0]-v[0][0]-v[1][0], k[1]-v[0][1]-v[1][1]):v for k, v in a.items()}
for key in list(a.keys()):
    new_key = []
    new_key.append(key[0] - (a[key][0][0] + a[key][1][0]))
    new_key.append(key[1] - (a[key][0][1] + a[key][1][1]))
    a[new_key] = a.pop(key) # pop() returns the value

Iterate through the dictionary to get the keys and values and create a new one b . Then just point a to the new dictionary b

a = {(8, 9): [[0, 0], [4, 5]], (3, 4): [[1, 2], [6, 7]]}
b = {}
for key, val in a.items():
    new_key = (key[0]-(val[0][0]+val[1][0]), key[1]-(val[0][1]+val[1][1]))
    b[new_key] = val
a = b
del b

Try This:

b = {}
for key, value in a.items():
    new_key = key[0]-(value[0][0]+value[1][0])
    new_key_1 = key[1]-(value[0][1]+value[1][1])
    u_key = (new_key, new_key_1)
    b[u_key]=value
print(b)

The following code will work just as well with any size of key tuple (2, 5, 87, whatever.)

There is no simple way to rename a dictionary key, but you can insert a new key and delete the old one. This isn't recommended for a couple of reasons:

If you need a dictionary result, the safest thing is to generate an entirely new dictionary based on a , as has been done here.

The problem you're trying to solve is easier if you transpose the dictionary values.

After calculating the new key, (8, 9): [[0, 0], [4, 5]] should become:

(8 - sum([0, 4]), 9 - sum([0, 5])): [[0, 0], [4, 5]] 

Now see how transposing helps:

transposed([[0, 0], [4, 5]]) == [[0, 4], [0, 5]]

then the new key[0] calculation is:

key[0] - sum(transposed(values)[0])

and the new key[1] calculation is:

key[1] - sum(transposed(values)[1])

So transposing makes the calculation easier.

Python dictionaries can't have lists as keys (lists are not hashable ) so I've built the key as a list, then converted it to a tuple at the end.

a = {
    (8, 9): [[0, 0], [4, 5]],
    (3, 4): [[1, 2], [6, 7]]
}

def transpose(m):
    return list(zip(*m))

results = {}
for source_keys, source_values in a.items():
    transposed_values = transpose(source_values)
    key = []
    for n, key_item in enumerate(source_keys):
        subtractables = sum(transposed_values[n])
        key.append(key_item - subtractables)
    results[tuple(key)] = source_values

print(results)

>>> python transpose.py
{(4, 4): [[0, 0], [4, 5]], (-4, -5): [[1, 2], [6, 7]]}

The following solution works with three assumptions:

  1. The keys are iterables of integers
  2. The values are iterables of iterables of integers
  3. The inner iterables of each value are the same length as the corresponding key

Practically, this means that the length of the value can be anything, as long as it's a 2D list, and that you can have keys of different lengths, even in the same dictionary, as long as the values match along the inner dimension.

You would want to transpose the values to make the sum easier to compute. The idiom zip(*value) lets you do this quite easily. Then you map sum onto that and subtract the result from the elements of the key.

Another thing to keep in mind is that replacing keys during iteration is a very bad idea. You're better off creating an entirely new dictionary to hold the updated mapping.

from operator import sub
from itertools import starmap

a = {(8, 9): [[0, 0], [4, 5]], (3, 4): [[1, 2], [6, 7]]}
b = {
    tuple(starmap(sub, zip(k, map(sum, zip(*v))))): v
    for k, v in a.items()
}

The result is

{(4, 4): [[0, 0], [4, 5]], (-4, -5): [[1, 2], [6, 7]]}

Here is an IDEOne Link to play with.

The full version of the loop would look like this:

b = {}
for k, v in a.items():
    vt = zip(*v)  # transposed values
    sums = map(sum, vt)  # sum of the 1st elements, 2nd elements, etc
    subs = zip(k, sums)  # match elements of key with sums to subtract
    diffs = starmap(sub, subs)  # subtract sums from key
    new_key = tuple(diffs)  # evaluate the generators
    b[new_key] = value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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