Home > front end >  Save a randomly generated value as both the key and value of a dict comprehension
Save a randomly generated value as both the key and value of a dict comprehension

Time:07-25

Within a dict comprehension, how can I use a randomly generated value as both the key and value?

In my example use case I want to generate some random numbers and use these as the input to a function. I would like to save the the random numbers as they key and the function output given these numbers as the value.

Something like the following, however this implementation would generate different arrays of random numbers for the key and value.

{
    tuple(sorted(rng.choice(1000, size=10, replace=False))): my_function(sorted(rng.choice(1000, size=10, replace=False)))
    for i in range(sample_size)
}

Reproducable example:

import numpy as np

rng = np.random.default_rng()

sample_size = 3


def my_function(x: np.array) -> int:
    return sum(x)


dictionary = {
    tuple(sorted(rng.choice(1000, size=3, replace=False))): my_function(sorted(rng.choice(1000, size=3, replace=False)))
    for i in range(sample_size)
}

An example output would be:

{(43, 70, 788): 2386, (56, 151, 613): 1074, (486, 645, 647): 2038}

The sum of the keys is not equal to the value because different random numbers were used. My desire is that the same random numbers are stored as the key and used in the function call. In this example it would mean that the sum of the keys was equal to the value.

CodePudding user response:

If you are using Python3.8 or newer you can use Assignment Expressions

{tuple((arr := sorted(rng.choice(1000, size=10, replace=False)))): my_function(arr) for i in range(sample_size)}

CodePudding user response:

In python 3.8 , you can use the := operator:

{(n:=tuple(sorted(rng.choice(1000, size=10, replace=False)))):my_function(n) for _ in range(sample_size)}

CodePudding user response:

Just re-write your code to use a generator expression:

dictionary = {tuple(v): my_function(v) for v in (sorted(rng.choice(1000, size=3, replace=False)) for _ in range(sample_size))}

Output (of a single run)

{(92, 325, 573): 990, (361, 840, 913): 2114, (470, 669, 891): 2030}

As an alternative, is to use map:

dictionary = {tuple(v): my_function(v) for v in
              map(lambda _: sorted(rng.choice(1000, size=3, replace=False)), range(sample_size))}

print(dictionary)

Output (of a single run)

{(45, 157, 889): 1091, (73, 353, 779): 1205, (275, 282, 633): 1190}

Both solutions will work in Python regardless of the version.

CodePudding user response:

One approach can be to generate all random numbers and then create dict.

dictionary = {rnd: my_function(rnd) for rnd in (tuple(sorted(rng.choice(1000, size=3, replace=False))) for _ in range(sample_size))}

# Explanation(Step-by-Step), Generate all random numbers.
# random_nums = [tuple(sorted(rng.choice(1000, size=3, replace=False))) for _ in range(sample_size)]

# then create a dictionary from each random number
# dictionary = {rnd : my_function(rnd) for rnd in random_nums}

Another approach, In python < 3.8, You can do with for-loop and a temporary variable like below:

sample_size = 5
dictionary = {}
for _ in range(sample_size):
    tmp = tuple(sorted(rng.choice(1000, size=3, replace=False)))
    dictionary[tmp] = my_function(tmp)
    
print(dictionary)

{
    (285, 520, 523): 1328, 
    (608, 736, 760): 2104, 
    (148, 449, 834): 1431, 
    (41, 800, 848): 1689, 
    (213, 502, 536): 1251
}
  • Related