开发者

Python: Confused about random.choice within join

Here is my code:

s = 'Hello world'
c = ['a','b','c','d','e','f']
n = ['1','2','3','4','5','6']
l = [random.choice(c),random.choice(n)]
return ''.join('%s%s' % (x, random.choice(l) if random.random() > 0.5 else '') for x in s)

This will output:

He5lloe w5o5rl5de

But what I am aiming for is something like this code would produce:

s = 'Hello world'
n = ['1','2','3','4','5','6']
return ''.join('%s%s' % (x, random.choice(n) if random.random() > 0.5 else '') for x in s)

Which is:

H4e3l3l6o wo4r3ld

It would be great if someone could also explain as to why the two are reacting differently than I would have assumed.

Sorry, I should have stated my intentions. I would like to randomly select an element from the two lists through each iteration of the for loop within join. Instead what I have is 2 elements being selected once and randomly choosing between the two elements selected.

This is what I don't want:

n = [1,2,3,4,5]
s = ['!','-','=','~','|']
l = [random.choice(n), random.choice(s)] # 1,!
# He1l!lo W!开发者_JAVA百科or1l!d

This is what I want:

n = [1,2,3,4,5] # 1 or 2 or 3... etc.
s = ['!','-','=','~','|'] # ! or - or =... etc.
> code to randomly select a list and a new element from that list
# He4ll-o W!or3l~d

Not sure if I have worded myself correctly, but hopefully it is understandable,


By doing l = [random.choice(c),random.choice(n)] you're limiting random.choice(l) to only 2 possible chars (one from each list c and n).

Try this instead:

from random import random, choice
s = 'Hello world'
c = ['a','b','c','d','e','f']
n = ['1','2','3','4','5','6']
L = choice([c, n])  # randomly choose either c or n
return ''.join('%s%s' % (x, choice(L) if random() > 0.5 else '') for x in s)

As an aside, assuming you want to keep the probability of an insertion at 0.5, that can also be written as:

# for each char, either append an empty string or a random char from list
return ''.join('%s%s' % (x, choice((choice(L), ""))) for x in s)

Update

Note that the above answer chooses a substitution list (c or n) and uses it for the whole process. If you want to be able to use both lists in the substitution, you can either create an intermediate list (L = c + n), or perform the list selection in-line.

# This is rather convoluted
return ''.join('%s%s' % (x, choice((choice(choice([c, n])), ""))) for x in s)

Alternatively,

e = ("", )  # tuple with a single empty element
return ''.join('%s%s' % (x, choice(choice([c, n, e, e]))) for x in s)
  • Choose between c, n, or empty list e (e appears twice to keep the non-empty probability at 50%. Change as required)
  • From the chosen list/tuple, choose a random element
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜