【发布时间】:2017-05-29 14:23:54
【问题描述】:
我有两个列表:
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2 = [1, 4, 5]
我想从list1 中选择一个元素,但它不应该属于list2。
我有一个使用 while 循环的解决方案,但我想要一个更 Python 和优雅的内衬。
【问题讨论】:
标签: 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 和优雅的内衬。
【问题讨论】:
标签: python python-3.x random conditional-statements
如果您的元素是独一无二的,您可以使用设置差异。 (将 list1 转换为一个集合并从 list2 中删除元素)。然后随机抽取一个样本。
random.choice(list(set(list1).difference(list2)))
【讨论】:
[item for item in list1 if not in list2]
为了让它更快一点(因为在集合中查找比在列表中更快):
list2_items = set(list2)
[item for item in list1 if not in list2_items]
或带有过滤功能(你将在 Python3 中得到一个生成器对象
filter(lambda item: item not in list2, list1)
将 list2 转换为 set 也会加快此处的过滤速度。
如需了解更多信息,请阅读list comprehensions。
更新:我似乎错过了关于一个随机值的观点。好吧,您仍然可以使用列表推导式,但使用前面提到的 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
【讨论】:
set 方法可能是错误的,因为它们需要可散列的值并且丢弃重复项(因此可能会倾斜概率)。也许检查一些元素是否保留在list1 中会很好,但否则很难有一个“一个人统治所有”的方法。在这种情况下,它很少需要超过 2 次尝试,它是 O(1),而 set-approaches 是 O(n),具有相当高的常数因子。
list2 中的元素的概率很高,那么在调用random.choice 之前 过滤list1 可能是值得的。跨度>
set 绝对是更好的选择。
您可能希望像这样使用sets:
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]))
【讨论】:
set(list1).difference(list2),你不需要构造一个显式的第二个集合。 difference 将任何可迭代对象作为参数,而不仅仅是一个集合。
set(list1).difference(list2),对吧?
set2, list2, 随便 :) 谢谢。
list1 中的所有重复项(不仅是list2 中存在的那些),因此会扭曲概率。
不导入随机库:
print((list(set(list1) - set(list2))).pop())
在 pop() 中你可以给出你想要选择的元素的索引,它会弹出那个元素
示例:用于选择索引 1 的列表(从新列表中),((list(set(list1) - set(list2))).pop(1))
这里(list(set(list1) - set(list2)) 代码将创建一个新列表,其中仅包含第一个列表中不存在于第二个列表中的项目,
【讨论】: