- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试创建一个生成器,该生成器返回给定范围内的数字,这些数字通过函数给出的特定测试 foo
.但是我希望以随机顺序测试这些数字。以下代码将实现这一点:
from random import shuffle
def MyGenerator(foo, num):
order = list(range(num))
shuffle(order)
for i in order:
if foo(i):
yield i
问题
此解决方案的问题在于,有时范围会非常大(num
的顺序可能是 10**8
或更高)。这个函数可能会变慢,因为内存中有这么大的列表。我已尝试使用以下代码避免此问题:
from random import randint
def MyGenerator(foo, num):
tried = set()
while len(tried) <= num - 1:
i = randint(0, num-1)
if i in tried:
continue
tried.add(i)
if foo(i):
yield i
这在大多数情况下都很有效,因为在大多数情况下 num
会很大,foo
将传递合理数量的数字和总次数 __next__
将被调用的方法将相对较小(例如,最多 200 个通常要小得多)。因此,我们很可能偶然发现一个通过 foo
的值。测试和大小 tried
永远不会变大。 (即使它只有 10% 的时间通过,我们也不会期望 tried
大致大于 2000。)
然而,当num
很小(接近 __next__
方法被调用的次数,或者 foo
大部分时间失败,上述解决方案变得非常低效 - 随机猜测数字,直到它猜到一个不在 tried
中的数字。 .
我尝试的解决方案...
我希望使用某种映射数字 0,1,2,..., n
的函数以一种大致随机的方式在自己身上。 (这不用于任何安全目的,因此如果它不是世界上最“随机”的功能也没关系)。这里的函数 ( Create a random bijective function which has same domain and range ) 将带符号的 32 位整数映射到自身,但我不确定如何将映射调整到更小的范围。鉴于 num
我什至不需要 0,1,..num
上的双射只是一个值 n
大于并“接近”num
(使用您认为合适的任何关闭定义)。然后我可以执行以下操作:
def mix_function_factory(num):
# something here???
def foo(index):
# something else here??
return foo
def MyGenerator(foo, num):
mix_function = mix_function_factory(num):
for i in range(num):
index = mix_function(i)
if index <= num:
if foo(index):
yield index
(只要双射不是在一组大大大于 num
的数字上,index <= num
不为真的次数就会很小)。
我的问题
你能想到以下其中一项吗:
mix_function_factory
的潜在解决方案甚至是 mix_function
的一些其他潜在功能我可以尝试概括 num
的不同值?提前致谢....
最佳答案
问题基本上是生成 0..n-1
范围内整数的随机排列。
对我们来说幸运的是,这些数字有一个非常有用的属性:它们都有一个不同的值模 n
。如果我们可以对这些数字应用一些数学运算,同时注意保持每个数字不同模 n
,就很容易生成一个看起来随机的排列。最好的部分是我们不需要任何内存来跟踪我们已经生成的数字,因为每个数字都是用一个简单的公式计算的。
我们可以对范围内的每个数字 x
执行的操作示例包括:
c
加到x
上。x
与任何与 n
没有质因数的数 m
相乘。仅在 0..n-1
范围内应用这两个操作已经给出了非常令人满意的结果:
>>> n = 7
>>> c = 1
>>> m = 3
>>> [((x+c) * m) % n for x in range(n)]
[3, 6, 2, 5, 1, 4, 0]
看起来很随意,不是吗?
如果我们从随机数生成 c
和 m
,它实际上也是 随机的。但请记住,不能保证此算法会生成所有可能的排列,或者每个排列都有相同的生成概率。
实现的困难部分实际上只是生成一个合适的随机 m
。我使用了 this answer 中的质因数分解代码这样做。
import random
# credit for prime factorization code goes
# to https://stackoverflow.com/a/17000452/1222951
def prime_factors(n):
gaps = [1,2,2,4,2,4,2,4,6,2,6]
length, cycle = 11, 3
f, fs, next_ = 2, [], 0
while f * f <= n:
while n % f == 0:
fs.append(f)
n /= f
f += gaps[next_]
next_ += 1
if next_ == length:
next_ = cycle
if n > 1: fs.append(n)
return fs
def generate_c_and_m(n, seed=None):
# we need to know n's prime factors to find a suitable multiplier m
p_factors = set(prime_factors(n))
def is_valid_multiplier(m):
# m must not share any prime factors with n
factors = prime_factors(m)
return not p_factors.intersection(factors)
# if no seed was given, generate random values for c and m
if seed is None:
c = random.randint(n)
m = random.randint(1, 2*n)
else:
c = seed
m = seed
# make sure m is valid
while not is_valid_multiplier(m):
m += 1
return c, m
现在我们可以为 c
和 m
生成合适的值,创建排列很简单:
def random_range(n, seed=None):
c, m = generate_c_and_m(n, seed)
for x in range(n):
yield ((x + c) * m) % n
你的生成器函数可以实现为
def MyGenerator(foo, num):
for x in random_range(num):
if foo(x):
yield x
关于python - 非常大范围的高效随机生成器(在 python 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49956883/
我使用以下代码和嵌套生成器迭代文本文档并使用 get_train_minibatch() 返回训练示例。我想保留( pickle )生成器,这样我就可以回到文本文档中的相同位置。但是,您不能 pick
在本教程中,您将借助示例了解 JavaScript 生成器。在 JavaScript 中,生成器提供了一种使用函数和迭代器的新方法。 使用生成器, 您可以从函数内部的任何位置停止执行函数 并从
LESS is very cool .我一直想知道是否有任何好的 html 生成器可以让我更轻松地编写表单或做其他事情。除了 html,是否有一些类似的东西? 最佳答案 已尝试 Haml ? 从它的网
前言 如果是做python或者其他语言的小伙伴,对于生成器应该不陌生。但很多php开发者或许都不知道生成器这个功能,可能是因为生成器是php 5.5.0才引入的功能,也可以是生成器作用不是很明显。
我正在尝试编写一个使用生成器语法生成日期时间列表的函数: let dateRange = let endDate = System.DateTime.Parse("6/1/2010")
我遇到了一些看起来像的代码: [func(val) for val in iterable] 有一个可迭代对象(在我的例子中是一个生成器),用户想要为其副作用调用每个值的函数(例如 func 可以只是
Delphi 有内置的东西来生成 UUID 吗? 最佳答案 program Guid; {$APPTYPE CONSOLE} uses SysUtils; var Uid: TGuid; Result
我正在深入研究 javascript 生成器,但我真的很困惑。 我使用 node@0.11.x 运行此示例: function find() { process.nextTick(functi
有人知道一些关于如何为 hibernate 创建自定义 ID 生成器的好教程吗? 最佳答案 在 Google 上粗略搜索“hibernate 自定义 id 生成器教程”发现了以下可能性。我排除了那些看
我正在关注 Python 大师 David Beazley 的幻灯片。它指出“生成器也用于并发。这是一个示例: from collections import deque def countdown(
我有一个生成事件的生成器,我想用可以从 API 获取的附加元数据来丰富它。 某些事件具有与其链接的对象 ID,而其他事件则具有对象的哈希值,但不能同时具有两者。我无法根据哈希获取对象 id,我只能执行
假设我有一个自定义类: public class CustomClass { private String name; private String data; public
我正在考虑实现一个函数来在 SQL 请求中“构建”WHERE 子句,如下所示: "SELECT * FROM table $where" 使用如下所示的循环构建 $where: $arr=array(
我正在寻找执行此操作的标准函数: def Forever(v): while True: yield v 这看起来太琐碎了,我不敢相信没有标准版本。 就此而言,有人知道指向所有标准生成器函
我知道这个网站上有几个非常相似的相关问题,但是在看了这部剧之后,我相信这个问题本身就是独一无二的。如果有人能找到并提供证据证明我的问题完全被骗了,我会自己撤回它(所以请不要否决这个!)。 我是 Jav
void __fastcall TForm1::Button1Click(TObject *Sender) { int size = MemoEnter->GetTextLen() + 1;
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我试图在我的生成器的以下两个定义之间做出决定。哪个更好?哪个“更像 python ”?无论如何,有没有办法减轻每一个的缺点? def myGenerator1(howMany): result
我有一个 Python 生成器 lexg,它在每次迭代时生成一个列表。该代码似乎在传统的 for 循环意义上工作,即 for i in lexg(2,2): print(i) 产生: [2, 0] [
我希望这不会超出 Python 生成器的能力,但我想构建一个这样,每次调用该函数时,它都会返回下一分钟直到结束时间。 因此该函数读取开始时间和结束时间,并以分钟为单位返回时间,直到涵盖其间的所有时间。
我是一名优秀的程序员,十分优秀!