Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Extracting values from non empty nested lists, randomly

I have the following list of objects in wich I would like to extract random values.

l = [
    {'A':[],'B':['b1','b2'],'C':[],'D':['d1','d2','d3'],'E':['e1']},
    {'A':['a4','a5','a6'],'B':['b6'],'C':['c4','c5','c6'],'D':[],'E':['e4','e5','e6']},
    {'A':['a7'],'B':['b7','b8'],'C':['c7','c8','c9'],'D':['d7','d8','d9'],'E':[]},
]

The goal is:
For each of the 3 objects in list l, extract one nested value randomly.
The result should be a list with 3 values in it.
Examples of possible results :
res = [‘b1′,’b6′,’d9’]
or res = [‘e1′,’c4′,’a7’]

I have tried using random.choice() but the problem is when random lands on an empty list…
If it does land on an empty list such as ‘A’ in the first object, then it has to try again until it lands on a non empty list.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

How can I acheive this?

>Solution :

Equal probability for lists

You can do a random choice on keys that have a list with value, then a choice between these values.

To do that, you need to filter empty lists. It’s easy to do that with a list comprehension and a filter:

[v for v in o.values() if v]

You need to choose a random key among keys with value (the filter we talked before) and then, choose a value in the list of the selected key.

import random

l = [
    {'A':[],'B':['b1','b2'],'C':[],'D':['d1','d2','d3'],'E':['e1']},
    {'A':['a4','a5','a6'],'B':['b6'],'C':['c4','c5','c6'],'D':[],'E':['e4','e5','e6']},
    {'A':['a7'],'B':['b7','b8'],'C':['c7','c8','c9'],'D':['d7','d8','d9'],'E':[]},
]

res = [random.choice(random.choice([v for v in o.values() if v])) for o in l]
print(res)
# ['e1', 'b6', 'd7']

This solution works this way with probabilities. Let’s take the first dictionary:

{'A':[],'B':['b1','b2'],'C':[],'D':['d1','d2','d3'],'E':['e1']},

The first choice will choose between ["b1", "b2"], ["d1", "d2", "d3"] and ["e1"], with 1/3 chance for each. This mean that the final distribution will be:

1/3: [
    1/6: "b1", 
    1/6: "b2",
],
1/3: [
    1/9: "d1",
    1/9: "d2",
    1/9: "d3",
],
1/3 [
    1/3: "e1",
],

Equal probability for leafs

If you need equal probability of leaf values instead of equal probability for lists, you don’t need to filter as the flattening comprehension will pass over empty lists without doing anything:

res = [random.choice([e for v in o.values() for e in v]) for o in l]

Distribution of values with this code is:

1/3: [
    1/6: "b1", 
    1/6: "b2",
],
1/2: [
    1/6: "d1",
    1/6: "d2",
    1/6: "d3",
],
1/6 [
    1/6: "e1",
],

Each leaf value of the dict is equally distributed.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading