Home > Mobile >  Adjust / norm python dictionary values to certain size / length
Adjust / norm python dictionary values to certain size / length

Time:07-06

I have a question regarding how to limit the value length of a dictionary:

real_vertrices_copy = {
     'key': {1,3,8,4,2},
     'key1': {9,4,2,4},
     'key2': {6,4,2},
     'key3': {9,3,5,3,5}
    }

The dictionary consists of key value pairs, with the values varying in length. I want to limit the length of the values to 3, so if the length of the values is > 3, I want to pop random elements as many times necessary to reduce it to len=3.

I tried it like this:

for x in real_vertrices_copy.values():
if len(x) > 20:
    real_vertrices_copy.popitem()
    

but this just removes random dictionary entries (I did not expect this to work, I have to admit)

Does anyone have an idea how to solve this?

Thank you and BR

CodePudding user response:

You could just pop three times from each set with more than three elements to get three arbitrary elements:

d = {
    'key': {1,3,8,4,2},
    'key1': {9,4,2,4},
    'key2': {6,4,2},
    'key3': {9,3,5,3,5}
}
d = {
    k: {v.pop() for _ in range(3)} if len(v) > 3 else v
    for k, v in d.items()
}

This assumes that there are no other references to the sets in d because the mutation via pop will be seen across all references.

CodePudding user response:

You can use a dictionary comprehension with random sampling (random.sample):

d = {'key': {1,3,8,4,2},
     'key1': {9,4,2,4},
     'key2': {6,4,2},
     'key3': {9,3,5,3,5}
    }

import random
out = {k: set(random.sample(list(v), 3)) for k,v in d.items()}

or, if it is possible that the input has less than 3 elements:

N = 3
out = {k: set(random.sample(list(v), N)) if len(v)>=N else v
       for k,v in d.items()}

example output:

{'key': {1, 3, 8}, 'key1': {2, 4, 9}, 'key2': {2, 4, 6}, 'key3': {3, 5, 9}}
classical loop

If you need a classical loop and want to get both kept and discarded items, take advantage of set operations:

N = 3
keep = {}
discard = {}
for k,v in d.items():
    keep[k] = set(random.sample(list(v), min(len(v), N)))
    discard[k] = v.difference(keep[k])
    
print(keep)
# {'key': {1, 2, 4}, 'key1': {9, 2, 4}, 'key2': {2, 4, 6}, 'key3': {9, 3, 5}}
print(discard)
# {'key': {8, 3}, 'key1': set(), 'key2': set(), 'key3': set()}

CodePudding user response:

Inplace update of real_vertrices_copy:

import random

real_vertrices_copy = {'key': {1,3,8,4,2},
     'key1': {9,4,2,4},
     'key2': {6,4,2},
     'key3': {9,3,5,3,5}
    }
for k, v in real_vertrices_copy.items():
    while len(v) > 3:
        v.remove(random.choice(tuple(v)))
  • Related