我需要一个Python函数,当给出所需的字符概率时,它将输出一个由4个不同字符组成的随机字符串

时间:2009-04-13 14:48:24

标签: python random

例如,  该函数可能类似def RandABCD(n,.25,.34,。25,。25):

其中n是要生成的字符串的长度,以下数字是A,B,C,D的所需概率。

我认为这很简单,但是我在创建工作程序时遇到了麻烦。任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:4)

这是选择单个加权值的代码。你应该可以从这里拿走它。它使用bisectrandom来完成工作。

from bisect import bisect
from random import random

def WeightedABCD(*weights):
  chars = 'ABCD'
  breakpoints = [sum(weights[:x+1]) for x in range(4)]
  return chars[bisect(breakpoints, random())]

这样称呼:WeightedABCD(.25, .34, .25, .25)

编辑:这是一个即使权重不等于1.0也能正常运行的版本:

from bisect import bisect_left
from random import uniform

def WeightedABCD(*weights):
  chars = 'ABCD'
  breakpoints = [sum(weights[:x+1]) for x in range(4)]
  return chars[bisect_left(breakpoints, uniform(0.0,breakpoints[-1]))]

答案 1 :(得分:2)

随机类在python中非常强大。您可以使用适当的权重生成包含所需字符的列表,然后使用random.choice获取选择。

首先,确保随机导入。

例如,假设您想要一个来自A,B,C或D的真正随机字符串。 1.生成包含字符的列表 li = ['A','B','C','D']

  1. 然后使用random.choice从中获取值 output =“”。join([random.choice(li)for i in range(0,n)])
  2. 你可以轻松地将这个函数作为n参数。

    在上述情况下,您获得A,B,C或D的机会相等。

    您可以使用列表中的重复条目为字符提供更高的概率。所以,举个例子,假设你想要A的概率为50%,B和C的概率为25%。你可以有这样一个数组:

    li = ['A','A','B','C']

    等等。

    使用所需的权重参数化字符并不困难,以模拟我使用字典。

    characterbasis = {'A':25,'B':25,'C':25,'D':25}

    将它设为第一个参数,第二个参数为字符串的长度,并使用上面的代码生成字符串。

答案 2 :(得分:2)

对于四个字母,这里有一些快速的东西:

from random import random

def randABCD(n, pA, pB, pC, pD):
    # assumes pA + pB + pC + pD == 1
    cA = pA
    cB = cA + pB
    cC = cB + pC
    def choose():
        r = random()
        if r < cA:
           return 'A'
        elif r < cB:
           return 'B'
        elif r < cC:
           return 'C'
        else:
           return 'D'
    return ''.join([choose() for i in xrange(n)])

我毫不怀疑这可以变得更清洁/更短,我现在只是有点匆忙。

我不满足于Dakota使用重复字符列表的答案的原因是,根据您的概率,可能无法创建一个包含正确数字重复的列表来模拟您的概率想。 (好吧,我想这可能永远是可能的,但你可能最终需要一个巨大的清单 - 如果你的概率是0.11235442079,0.4072777384,0.2297927874,0.25057505341怎么办?)

编辑:这是一个更清晰的通用版本,适用于任意数量的任何重量的字母:

from bisect import bisect
from random import uniform

def rand_string(n, content):
    ''' Creates a string of letters (or substrings) chosen independently
        with specified probabilities. content is a dictionary mapping
        a substring to its "weight" which is proportional to its probability,
        and n is the desired number of elements in the string.

        This does not assume the sum of the weights is 1.'''
    l, cdf = zip(*[(l, w) for l, w in content.iteritems()])
    cdf = list(cdf)
    for i in xrange(1, len(cdf)):
        cdf[i] += cdf[i - 1]
    return ''.join([l[bisect(cdf, uniform(0, cdf[-1]))] for i in xrange(n)])        

答案 3 :(得分:0)

以下是您可能适合自己的概念

import random as r

def distributed_choice(probs):
    r= r.random()
    cum = 0.0

    for pair in probs:
        if (r < cum + pair[1]):
            return pair[0]          
        cum += pair[1]

参数probs采用表格对象(对象,概率)的列表。假设概率之和为1(否则,它很难归一化)。

要使用它,只需执行:

''.join([distributed_choice(probs)]*4)

答案 4 :(得分:0)

嗯,有点像:

import random
class RandomDistribution:
    def __init__(self, kv):
        self.entries = kv.keys()
        self.where = []
        cnt = 0
        for x in self.entries:
            self.where.append(cnt)
            cnt += kv[x]
        self.where.append(cnt)   

    def find(self, key):
        l, r = 0, len(self.where)-1
        while l+1 < r:
           m = (l+r)/2
           if self.where[m] <= key:
               l=m
           else:
               r=m
        return self.entries[l]

    def randomselect(self):
        return self.find(random.random()*self.where[-1])

rd = RandomDistribution( {"foo": 5.5, "bar": 3.14, "baz": 2.8 } )
for x in range(1000):
    print rd.randomselect()

应该让你大部分时间......

答案 5 :(得分:0)

谢谢大家的帮助,我能够解决一些问题,主要是这些信息。 根据我的特殊需要,我做了类似的事情:

import random
#Create a function to randomize a given string
def makerandom(seq):
    return ''.join(random.sample(seq, len(seq)))
def randomDNA(n, probA=0.25, probC=0.25, probG=0.25, probT=0.25):
    notrandom=''
    A=int(n*probA)
    C=int(n*probC)
    T=int(n*probT)
    G=int(n*probG)

#The remainder part here is used to make sure all n are used, as one cannot
#have half an A for example.
    remainder=''
    for i in range(0, n-(A+G+C+T)):
        ramainder+=random.choice("ATGC")
    notrandom=notrandom+ 'A'*A+ 'C'*C+ 'G'*G+ 'T'*T + remainder
    return makerandom(notrandom)