def weighted_sample(L, x):
# might consider raising some kind of exception of len(set(L)) < x
while True:
ans = random.sample(L, x)
if len(set(ans)) == x:
return ans
如果你想要很多这样的样品,你可以做如下的事情:
[weighted_sample(L, x) for _ in range(num_samples)]
def weighted_sample(L, x):
ans = []
c = collections.Counter(L)
while len(ans) < x:
r = random.randint(0, sum(c.values())
for k in c:
if r < c[k]:
ans.append(k)
del c[k]
break
else:
r -= c[k]
else:
# maybe throw an exception since this should never happen on valid input
return ans
>>> 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]
。。或者,按照FMc的简化:
>>> [x for x in random.choice([p for p in itertools.permutations(s, 3) if len(set(p)) == 3])]
[3, 5, 2]
(我将把x for x放在那里,即使不简单地写list(random.choice(..))或仅仅把它作为元组..)
>>> 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]]
请不要使用这个代码——我只是出于好玩/学术的原因才发的。
其工作原理如下:
我在列表理解中创建了一个函数,默认参数是从输入列表中随机选择的3个元素。在函数内部,我将元素从values中移除,这样它们就不能再被拾取。由于list.remove返回None,我可以使用any(lst.remove(x) for x in ...)删除值并返回False。由于any返回False,因此在调用函数时,我们命中了or子句,该子句只返回x(带有3个随机选择项的默认值)。剩下的就是调用函数,让魔法发生。
如果我能正确理解你的问题,这应该行得通:
如果你想要很多这样的样品,你可以做如下的事情:
我很难想象对抽样逻辑的理解不仅仅是模糊的。逻辑有点太复杂了。对我来说,这听起来像是一个随机的附加在家庭作业上的东西。
如果你不喜欢无限循环,我还没有试过,但我认为这是可行的:
免责声明:“使用列表理解”的要求是荒谬的。
此外,如果您想使用权重,在Eli Bendersky的weighted random sampling页面上列出了许多优秀的方法。
以下是低效,不可扩展等
也就是说,它不是一个而是两个(两个!)列表理解,返回列表,从不重复元素,并在某种意义上尊重权重:
。。或者,按照FMc的简化:
(我将把
x for x
放在那里,即使不简单地写list(random.choice(..))
或仅仅把它作为元组..)一般来说,您不想在列表理解中做这种事情——这将导致更难阅读代码。然而,如果你真的必须这样做,我们可以写一个非常可怕的1行:
请不要使用这个代码——我只是出于好玩/学术的原因才发的。
其工作原理如下:
我在列表理解中创建了一个函数,默认参数是从输入列表中随机选择的3个元素。在函数内部,我将元素从
values
中移除,这样它们就不能再被拾取。由于list.remove
返回None
,我可以使用any(lst.remove(x) for x in ...)
删除值并返回False
。由于any
返回False
,因此在调用函数时,我们命中了or
子句,该子句只返回x
(带有3个随机选择项的默认值)。剩下的就是调用函数,让魔法发生。这里的一个问题是,您需要确保您请求的组数(这里我选择了4)乘以每个组的项数(这里我选择了3)小于或等于输入列表中的值数。这看起来很明显,但无论如何可能值得一提。。。
下面是我将
shuffle
放入列表理解的另一个版本:这比我的第一次尝试要好得多,但是,大多数人仍然需要停下来,挠挠头,然后才知道这段代码在做什么。我仍然断言,多行这样做会更好。
相关问题 更多 >
编程相关推荐