如何从列表中删除项目并将其添加到同一列表的末尾

时间:2020-05-09 03:04:01

标签: python list shuffle

我有一个52个元组(一副扑克牌)的列表,我试图在不使用random.shuffle的情况下进行混洗(不允许在该项目中使用它)。我想做的是创建2个随机索引,从列表中删除这些项目,然后在列表的最前面放置1个,在列表的末尾放置1个。

我可以创建随机#,但不确定如何移动它们。似乎.pop是我最好的方法,但不确定是否正确。

def shuffle():
    ite = 0
    while ite <= 1000:
        rand1 = randint(0, len(card_deck) -1)
        rand2 = randint(0, len(card_deck) -1)
        card_deck.pop[rand1]
        card_deck.append(rand1)
        ite += 1
shuffle()

3 个答案:

答案 0 :(得分:2)

在这种情况下,Pop的时间复杂度并不理想。将rand1的值存储为临时变量并将其替换为rand2的值,然后将rand2的值替换为临时变量会更有意义。而且,如下面的注释所述,效率更高,您可以交换两个值而无需使用临时变量。

例如,如果您有1000个项目的列表,并且想要弹出第500个项目,则它将在N(500)时间内运行。而您可以在固定时间内访问列表中的项目。

如果您是在做家庭作业,请尝试在未亲自执行的情况下查看下面的答案。

def shuffle():
    ite = 0
    while ite <= 1000:
        rand1 = randint(0, len(card_deck) - 1)
        rand2 = randint(0, len(card_deck) - 1)
        card_deck[rand1], card_deck[rand2] = card_deck[rand2], card_deck[rand1]
        ite += 1

答案 1 :(得分:0)

正如@Sean Payne指出的那样; pop()并非可行之路。当您只想在值周围交换时,pop()会非常慢。 Python允许(鼓励)元组分配,因此人们可以在不使用临时存储位置x, y = y, x或在这种情况下为deck[i], deck[j] = deck[j], deck[i]的情况下交换值。

for循环比while循环更具蟒蛇性。

我猜想您的老师正在设法让您编写适当的Knuth混洗(link),也称为Fisher-Yates或Fisher-Yates-Knuth。 Durstenfeld是该算法的另一个重要贡献者。

import random

def shuffle(deck):
    for i in range(len(deck)-1, 0, -1):
        j = random.randint(0,i)
        deck[i], deck[j] = deck[j], deck[i]
    return deck

mydeck = list(range(52))
print(mydeck)
print(shuffle(mydeck))

Try it online!

要注意的最大区别是,一旦选择了要处理的项目到列表的末尾,就将其保留在那里。如果您继续生成数字,以允许对已经洗牌的项目进行重新洗牌,那么实际上会降低洗牌的随机性。 Mike BostockJeff Atwood对这个问题都有很好的解释。

如果您真的想要前后移动,可以执行类似的操作

import random

def shuffle2(deck):
    back_of_deck = len(deck) - 1
    for i in range(len(deck)//2):
        front = random.randint(i,back_of_deck)
        back = random.randint(i,back_of_deck)
        deck[i], deck[front] = deck[front], deck[i]
        deck[back_of_deck], deck[back] = deck[back], deck[back_of_deck]
        back_of_deck -= 1
    return deck

mydeck = list(range(52))
print(mydeck)
print(shuffle2(mydeck))

Try it online!

答案 2 :(得分:0)

我认为这就是您要寻找的

import random

def build_deck():
    '''
    build a fresh sorted deck of cards
    '''
    nums = range(1,14)
    types = ['Heart','Spade','Club','Diamond']
    deck = [(x,y) for x in types for y in nums]
    return deck


def get_random_indices(from_=1,to=50):
    '''
    get 2 random indices to choose from which are not similar
    '''
    index1 = random.randint(from_,to)
    index2 = random.randint(from_,to)
    if index1 == index2:
        index1,index2 = get_random_indices(from_,to)
    return index1,index2


def shuffle_deck(deck,n_times=52):
    '''
    shuffle deck n times
    '''
    if n_times>0:
        index1,index2 = get_random_indices()
        card1 = deck.pop(index1)
        card2 = deck.pop(index2)
        deck.append(card1)
        deck.insert(0,card2)
        n_times-=1
        shuffle_deck(deck,n_times=n_times)
    return deck

deck = build_deck()
new_deck = shuffle_deck(deck,52)
new_deck

您可以通过使用random.choice()选择是插入还是附加card1来增加随机性。