Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
最具python风格的方法是在带有条件的列表中随机选择一个元素_Python_Python 3.x_Random_Conditional Statements - Fatal编程技术网

最具python风格的方法是在带有条件的列表中随机选择一个元素

最具python风格的方法是在带有条件的列表中随机选择一个元素,python,python-3.x,random,conditional-statements,Python,Python 3.x,Random,Conditional Statements,我有两份清单: list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] list2 = [1, 4, 5] 我想从list1中选择一个元素,但它不应该属于list2 我有一个使用while循环的解决方案,但我希望有一个更具python风格和优雅的单行程序 [item for item in list1 if not in list2] 要使其更快一点(因为在集合中查找比在列表中查找快): 或者使用filter函数(您将在Python3中获得一个生成器对象) filte

我有两份清单:

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2 = [1, 4, 5]
我想从
list1
中选择一个元素,但它不应该属于
list2

我有一个使用while循环的解决方案,但我希望有一个更具python风格和优雅的单行程序

[item for item in list1 if not in list2]
要使其更快一点(因为在集合中查找比在列表中查找快):

或者使用filter函数(您将在Python3中获得一个生成器对象)

filter(lambda item: item not in list2, list1)
将list2转换为set也将加快此处的过滤速度

要获得更多信息,请阅读

更新:关于一个随机值,我似乎遗漏了一点。好吧,您仍然可以使用列表理解,但使用
random.choice
,如前所述:

import random
random.choice([item for item in list1 if not in list2_items])
它将筛选选择,然后随机获得一个。@zeehio响应看起来是更好的解决方案

import random
import itertools

next(item for item in (random.choice(list1) for _ in itertools.count()) if item not in list2)
这相当于:

while True:
    item = random.choice(list1)
    if item not in list2:
        break

如果元素是唯一的,可以使用集合差异。(将列表1转换为集合,并从列表2中删除元素)。然后随机抽取一个样本

random.choice(list(set(list1).difference(list2)))

您可能希望利用
设置
s,如下所示:

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2 = [1, 4, 5]

import random

print(random.choice([x for x in set(list1).difference(list2)]))  # kudos @chepner
这样,我们就可以从
set(list1)-set(list2)
中随机抽取
list1
中的元素,而不是
list2
中的元素。这种方法还可以在列表1和列表2变大时进行扩展


@MSeifert注意到,将
list1
转换为
set
将删除
list1
中可能存在的任何重复元素,从而改变概率。如果
list1
在一般情况下可能包含重复元素,则您可能希望这样做:

print(random.choice([x for x in list1 if x not in list2]))

不导入随机库:

print((list(set(list1) - set(list2))).pop())
在pop()中,您可以给出要选择的元素的索引,它将弹出该元素 示例:用于选择索引1的列表(从新列表),
((列表(设置(列表1)-set(列表2))).pop(1))


这里的
(list(set(list1)-set(list2))
代码将创建一个新列表,其中只包含第一个列表中的项目,而这些项目在第二个列表中不存在,

尝试以下操作:使用
set(list1).差异(list2)
,您不需要构造第二个显式集合。
difference
将任何iterable作为参数,而不仅仅是集合。@chepner那么您可能是指
set(list1)。difference(list2)
,对吧?
set2
list2
,随便:)谢谢。还需要注意的是,这将丢弃
列表1
中的任何重复项(不仅仅是
列表2
中的重复项)因此会扭曲概率。没有错,但可能需要无限次迭代的东西感觉不对劲。@chepner没错,但是
set
方法可能是错误的,因为它们需要散列值并丢弃重复项(因此可能会扭曲概率)。也许检查一些元素是否仍保留在
列表1
中会很好,但否则很难有一个“一个来统治所有元素”的方法。在这种情况下,它很少需要超过2次尝试,它是
O(1)
,而
-方法是
O(n)
具有相当高的常数因子。如果选择出现在
列表2
中的元素的概率很高,则在调用
random.choice
之前过滤
list1
可能是值得的。这是正确的。对于包含哈希值
set
的长iterables,显然是更好的选择。注意当什么都不符合标准时,无限循环这并不能解决随机选择。是的,谢谢你指出。我错过了问题标签,误解了它。
print((list(set(list1) - set(list2))).pop())