如何使用变量定义需要删除的随机值,从特定子列表中删除随机选择的值?

时间:2019-05-10 03:11:03

标签: python list random

我正在尝试创建一个函数,该函数从子列表中获取随机变量,并在选择后将其删除。但是出于某种原因,当我使用变量定义要删除的内容时,它会从多个子列表中删除,而实际上根本没有从这些子列表中删除任何内容?我不能很好地形容这件事,因为我自己不太了解。这是我为尝试重现该问题而编写的一些代码:


greet = [[1,"Hello!"],[2,"Hi!"], [3,"Howdy!"]]
person = [["John", greet], ["Sally", greet], ["Frank", greet]]

while True:

    #This is meant to catch the error random gives when there is an empty list, so it continues if there's an empty list.
    #When all lists in person[0][1] and [1][1] and so on and so forth are empty, there is a break function below.

    try:  
        person_select = random.choice(person)
        greet_select = random.choice(person_select[1])
        person_and_greet_order = [person_select[0], greet_select[1], greet_select[0]]
        print(person_and_greet_order)

        #This should be activating, but it isn't, leading to an infinite loop
        if person[0][1]==[] and person[1][1]==[] and person[2][1]==[]:
            print("Everyone greeted!")
            break

        #Tests to see if greeting was used on person, then remove that greeting from the list so it can't be used again.
        elif person_and_greet_order[0]=="John":
            person[0][1].remove(greet_select)
            print(person)
        elif person_and_greet_order[0]=="Sally":
            person[1][1].remove(greet_select)
            print(person)
        elif person_and_greet_order[0]=="Frank":
            person[2][1].remove(greet_select)
            print(person)

            #The else is here to see if it's properly detecting the names. 
        else:
            break
    except:
        continue

这是您将从中得到的:

[['John', [[2, 'Hi!'], [3, 'Howdy!']]], ['Sally', [[2, 'Hi!'], [3, 'Howdy!']]], ['Frank', [[2, 'Hi!'], [3, 'Howdy!']]]]
['John', 'Hi!', 2]
[['John', [[3, 'Howdy!']]], ['Sally', [[3, 'Howdy!']]], ['Frank', [[3, 'Howdy!']]]]
['Frank', 'Howdy!', 3]
[['John', []], ['Sally', []], ['Frank', []]]

(此后循环到无穷大,因为if语句看不到列表是空的,即使它们是空的?)

如您所见,当我需要从一个子列表中删除一个值时,它会从每个子列表中删除该值,而不是从特定子列表中删除。并且即使空白列表为空,它们也不会注册为空白列表。最终目标是使问候和人的所有可能的组合。我真的是python的新手,我不知道在这里能做什么。我在尽头。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

您在greet中使用了对person的相同引用,这是错误的,应该做的是在{{1}中使用greet的副本}列表,而不要使用person

要扩展,像greet[:]这样的赋值并不会创建一个列表的真实副本,而是最终导致发生的结果是两个变量都指向内存中的同一列表。 因此,更改b = a中的内容也会反映在a

要实际创建副本,我们需要像对b所做的那样b = a[:]

因此更新后的代码将如下所示

greet[:]

输出将是

import random
greet = [[1,"Hello!"],[2,"Hi!"], [3,"Howdy!"]]

#Use a copy of greet via list slicing
person = [["John", greet[:]], ["Sally", greet[:]], ["Frank", greet[:]]]

while True:

    #This is meant to catch the error random gives when there is an empty list, so it continues if there's an empty list.
    #When all lists in person[0][1] and [1][1] and so on and so forth are empty, there is a break function below.

    try:  
        person_select = random.choice(person)
        greet_select = random.choice(person_select[1])
        person_and_greet_order = [person_select[0], greet_select[1], greet_select[0]]
        print(person_and_greet_order)

        #This should be activating, but it isn't, leading to an infinite loop
        if person[0][1]==[] and person[1][1]==[] and person[2][1]==[]:
            print("Everyone greeted!")
            break

        #Tests to see if greeting was used on person, then remove that greeting from the list so it can't be used again.
        elif person_and_greet_order[0]=="John":
            person[0][1].remove(greet_select)
            print(person)
        elif person_and_greet_order[0]=="Sally":
            person[1][1].remove(greet_select)
            print(person)
        elif person_and_greet_order[0]=="Frank":
            person[2][1].remove(greet_select)
            print(person)

            #The else is here to see if it's properly detecting the names. 
        else:
            break
    except:
        continue

答案 1 :(得分:0)

发生这种情况是因为(默认情况下)列表是通过python中的引用复制的。将greet添加到人员数组时,请尝试将greet替换为deepcopy(greet)。这样会在内存中单独创建该列表的副本,因此更改它不会影响您的其他列表。

这需要额外导入from copy import deepcopy