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)))