2012-10-22 159 views
1

我想要做的是,有一个字符列表,每个字符都是一个过程,然后我想从这个列表中随机选择(或随机伪造,无关紧要)并执行该过程,那么我希望能够再次运行它,并且不会获得相同的值,例如,如果我有五个值,我希望能够运行它5次,那么我第6次运行它,它什么都不返回。下面是代码:从列表中选择唯一的值

from Tkinter import* 
from random import randint 
Characters=[Percy,Annabeth,Leo,Chuck,Sarah] 
Used = [] 
def callback(): 
    end = len(Characters)-1 
    rando = randint(0,end) 
    Characters[rando] 
    for i in Characters: 
     if Characters[rando] in Used: 
      print 'This has already been used' 
     else: 
      Characters[rando]() 
      Used.append(Characters[rando]) 
      break 


game = Tk() 
game.geometry('50x50+700+100') 
Button1 = Button(game,text = '1',command =lambda:callback()) 
Button1.pack(side=LEFT) 


game.mainloop() 

我试图让

callback() 

正常运行,我曾尝试你所看到的,但我也试图

if Characters[rando] in Used: 
    print 'This has already been used' 
else: 
    Characters[rando] 
    Used.append(Characters[rando]) 

在这两种情况下,将多次运行相同的程序,例如,'Leo'可能会连续执行3次。我搜索了几个小时寻找方法来做到这一点,但我找不到一个。

+0

这有在这里得到了很好的回答:http://stackoverflow.com/questions/3791400/how-can-you-select-a-random-element-from-a-list-and-have-it-be-removed – minism

回答

7

首先,我shuffleCharacters

Characters = [Percy,Annabeth,Leo,Chuck,Sarah] 
random.shuffle(Characters) 

现在,当你运行你的回调,你pop一个字符出来:

def callback(): 
    try: 
     C = Characters.pop() #popping the last one is more efficient than the first. 
    except IndexError: 
     return None 

    return C() 

因为这会破坏Characters,你可能要保持它的副本,以重置,如果你需要:

random.shuffle(Characters) 
Characters_save = Characters[:] 

def reset_characters(): 
    Characters[:] = Characters_save[:] 
+2

你不'需要为'.pop()'指定一个索引,只是让它弹出最后一个,因为它是效率最高的 –

+0

@JonClements - 为了效率,我将它改为了'.pop(-1)',但是你是对的。没有必要在这里指定。更新。 – mgilson

+0

'shuffle'也在原地,所以返回'None',你需要在*洗牌之前保存* –

0

完全未经检验的 - 但你可以实现一个基本类:

from random import shuffle 

class CallNext(object): 
    def __init__(self, vals): 
     self.vals = vals[:] 
     shuffle(self.vals) 
     self.iter = iter(self.vals) 
    def __call__(self): 
     try: 
      next(self.iter)() 
     except StopIteration as e: 
      pass # or do something smarter? 

另一种选择,而不是追赶StopIteration是使用:

next(self.iter, lambda: None)() 

然后有:

Button1 = Button(game, text='1', command=CallNext(Characters))