4

I am very new to Python (and coding in general). I am trying to create a function which creates a duplicate of a list, with any instances of the string "rand" replaced with a random integer. The function will be called several times, with a new input_list each time. These new items should be appended to the existing output list. We can assume there will be no repeated integers, but the "rand" string may appear many times. This is my current code. It does very close to what I want except that when the random number is already on the list, it just moves on to the next item rather than trying to create a new random number. Can anyone help me out with this? Thank you in advance.

import random
input_list = [1, 3, "rand", 2]
def number_adder(input_list):
  output_list = []

  for item in my_list:
    if item == "rand":
      new_variable = int(random.randint(0, 4))
      if new_variable in output_list:
        continue
    else:
      new_variable = item

  output_list.append(new_variable)
return output_list
8
  • 2
    Can you include a specific example of an output list that is different from what you expect, and also the result you actually wanted to achieve? Commented Jan 15, 2018 at 16:23
  • 1
    "When the function is done, it will receive a new input list. Which is then to be appended to the same output list." Please illustrate this in an example, as I'm not sure exactly what this means. Commented Jan 15, 2018 at 16:24
  • 3
    When you want to check for equality you should use == thus if item == "rand" . Commented Jan 15, 2018 at 16:24
  • thank you @kingJulian. I fixed it. Commented Jan 15, 2018 at 16:31
  • 1
    @RyanLague did you notice that you assign a number/string to a list (output_list = item)? Commented Jan 15, 2018 at 16:32

3 Answers 3

2
import random

input_list = [1, 3, "rand", 2]
output_list = []

options = set(range(5))
for item in input_list:
  if item == "rand":
    new_variable = random.choice(list(options))
  else:
    new_variable = item
  output_list.append(new_variable)
  options -= set([ new_variable ])

You could do it like this. But this would mean that in if no random number can be found which is possible anymore, then this will throw an exception.

This will keep a set of remaining options which is reduced whenever a new value is added to the output list. Whenever a random number is needed, it will use choice to take a random element from that set. This way you do not have to use a loop to call the random functions repeatedly until you find a valid random number.

A loop might seem feasible at first until you get to larger numbers so that you have to retry a lot until you find a valid random number (e. g. randint(0, 100000) in a list of 99990 elements). This would unnecessarily slow your code down.

Actually, I'd rephrase the code a little, using a generator:

def fill_randoms(list_with_randoms, options):
  for item in list_with_randoms:
    value = random.choice(list(options)) if item == 'rand' else item
    yield value
    options -= set([ value ])

And I'd call it like this:

list(fill_randoms([1, 3, "rand", 2], set(range(5))))

But if you are not familiar with generators, stick to the other code.

Sign up to request clarification or add additional context in comments.

10 Comments

Did you choose range(5) for the options variable because the list consisted of 4 items? Would len(input_list) + 1 be the same?
random.randint(0,4) delivers values from the set (0,1,2,3,4). range(5) contains also these values.
What's the point of using a set if you convert it to a list all the time?
I want to remove values from it all the time. Finding items in a set is cheaper than in a list because there they are hashed. And I only have to convert it to a list because random.choice() is too stupid to take a set (which it should, really). The main reason is: It logically is a set. The values therein have no order. To reflect that, use a set.
I just managed to get it working with your first version (my code is a little more complicated, getting its range from variables and don't a few other procedures before the last 2 lines and I'm a little slow at figuring this stuff out). In any case, worked like a charm!
|
1

Loop while the number is in the output list:

if item == "rand": 
    new_variable = int(random.randint(0, 4))
    while new_variable in output_list:
        new_variable = int(random.randint(0, 4))

3 Comments

The = operator is NOT a comparison operator in Python. You need to use == or other existing operators if you want your code not to fail.
@StefanPochmann Yeah you're right. I corrected the mistake to let it be, even if the OP seems to have his requirements.
Yeah, now it looks alright. Though I'd use while True and break to avoid the code duplication.
1

I fixed the error pointed out in the comments. Here are two functions that satisfy your ask:

import random
input_list = [1, 3, "rand", 2]

def rand_replacer(my_list):
    output_list = []
    for item in my_list:
        if item == "rand":
            while True:
                new_variable = random.randint(0, 4)
                if new_variable not in my_list:
                    output_list.append(new_variable)
                    break
        else:
            output_list.append(item)
    return output_list

3 Comments

Fantastic. Thank you! I will use your first function in the short term, as it is understandable with my current knowledge and also look into numpy.
The first solution will add no value to your output if the random number it chooses is already in the output. I don't think that is what you want. The second (numpy) will not check for random numbers already existing in the output list. So both are flawed.
I'm experimenting with this now, @Alfie, and you are correct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.