我有一个类似于的列表:
[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(..))或者只是把它作为一个元组来伤害...)
一般来说,你不想在列表理解中做这种事情——这会导致代码更难阅读。然而,如果你真的必须这样做,我们可以写一个完全可怕的 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)
这比我的第一次尝试要好得多,但是,大多数人在弄清楚这段代码在做什么之前仍然需要停下来,挠挠头。我仍然断言,在多行中执行此操作会更好。
| 归档时间: |
|
| 查看次数: |
6961 次 |
| 最近记录: |