Python随机列表理解

bra*_*oom 5 python

我有一个类似于的列表:

[1 2 1 4 5 2 3 2 4 5 3 1 4 2] 
Run Code Online (Sandbox Code Playgroud)

我想从此列表中创建一个x随机元素列表,其中所选元素都不相同.困难的部分是我想通过使用列表理解来做到这一点......如果x = 3,那么可能的结果是:

[1 2 3]
[2 4 5]
[3 1 4]
[4 5 1]
Run Code Online (Sandbox Code Playgroud)

等等...

谢谢!

我应该指定我不能将列表转换为集合.抱歉! 我需要随机选择的数字进行加权.因此,如果1在列表中出现4次,3在列表中出现2次,那么1是被选中的两倍......

DSM*_*DSM 10

免责声明:"使用列表理解"的要求是荒谬的.

此外,如果您想使用权重,Eli Bendersky的页面上列出了许多关于加权随机抽样的优秀方法.

以下是效率低下,无法扩展等等.

也就是说,它只有两个(两个!)列表推导,返回一个列表,从不复制元素,并在某种意义上尊重权重:

>>> s = [1, 2, 1, 4, 5, 2, 3, 2, 4, 5, 3, 1, 4, 2]
>>> [x for x in random.choice([p for c in itertools.combinations(s, 3) for p in itertools.permutations(c) if len(set(c)) == 3])]
[3, 1, 2]
>>> [x for x in random.choice([p for c in itertools.combinations(s, 3) for p in itertools.permutations(c) if len(set(c)) == 3])]
[5, 3, 4]
>>> [x for x in random.choice([p for c in itertools.combinations(s, 3) for p in itertools.permutations(c) if len(set(c)) == 3])]
[1, 5, 2]
Run Code Online (Sandbox Code Playgroud)

..或者,由FMc简化:

>>> [x for x in random.choice([p for p in itertools.permutations(s, 3) if len(set(p)) == 3])]
[3, 5, 2]
Run Code Online (Sandbox Code Playgroud)

(我会x for x留在那里,即使只是简单地写list(random.choice(..))或者只是把它作为一个元组来伤害...)


mgi*_*son 6

一般来说,你不想在列表理解中做这种事情——这会导致代码更难阅读。然而,如果你真的必须这样做,我们可以写一个完全可怕的 1 行:

>>> values = [random.randint(0,10) for _ in xrange(12)]
>>> values
[1, 10, 6, 6, 3, 9, 0, 1, 8, 9, 1, 2]
>>> # This is the 1 liner -- The other line was just getting us a list to work with.
>>> [(lambda x=random.sample(values,3):any(values.remove(z) for z in x) or x)() for _ in xrange(4)]
[[6, 1, 8], [1, 6, 10], [1, 0, 2], [9, 3, 9]]
Run Code Online (Sandbox Code Playgroud)

请永远不要使用此代码——我发布它只是出于娱乐/学术原因。

它的工作原理如下:

我在列表推导式中创建了一个函数,其默认参数为从输入列表中随机选择的 3 个元素。在函数内部,我从中删除了元素,values以便它们无法再次被选取。由于list.removereturn None,我可以使用any(lst.remove(x) for x in ...)删除值并 return False。由于anyreturns False,我们在调用函数时命中了or仅返回(具有 3 个随机选择项的默认值)的子句。x剩下的就是调用该函数并让奇迹发生。

这里的一个问题是,您需要确保您请求的组数(这里我选择了 4)乘以每组的项目数(这里我选择了 3)小于或等于您的值的数量输入列表。这可能看起来很明显,但无论如何它可能值得一提......

shuffle这是我引入列表理解的另一个版本:

>>> lst = [random.randint(0,10) for _ in xrange(12)]
>>> lst
[3, 5, 10, 9, 10, 1, 6, 10, 4, 3, 6, 5]
>>> [lst[i*3:i*3+3] for i in xrange(shuffle(lst) or 4)]
[[6, 10, 6], [3, 4, 10], [1, 3, 5], [9, 10, 5]]
Run Code Online (Sandbox Code Playgroud)

这比我的第一次尝试要好得多,但是,大多数人在弄清楚这段代码在做什么之前仍然需要停下来,挠挠头。我仍然断言,在多行中执行此操作会更好。