好的,我已经编写了一个函数/方法,其中我在某个 if 条件失败后执行一些操作,但只有 1-2 次为真。
这是我的代码:
def solve_current_level(self):
self.remaining_possibilities = list(self.remaining_possibilities)
if len(self.remaining_possibilities) > 10 ** 6:
#self.reduce_weapon_options()
pass
guess = list(random.choice(self.remaining_possibilities))
response = self.client.solve_level(self.current_level.levelNum, guess)
if 'roundsLeft' in response:
self.reset_remaining_possibilities()
return None
elif 'response' not in response:
return response
self.remaining_possibilities=[possibility for possibility in self.remaining_possibilities if game.Game_evaluate(guess, list(possibility)) == response['response']]
return None
Run Code Online (Sandbox Code Playgroud)
现在,当生成非常大的排列然后转换为列表以检查长度是否超过 10**6 时,就会出现问题,然后执行其他操作并返回。这是我目前的解决方案,但问题是当它变得非常庞大的脚本被杀死时。我从 ruby 转换了这段代码,在 ruby 中,可以在不转换为列表的情况下获得枚举器的大小,并且这个问题从未发生过。
这是 ruby 中的代码:
def solve_current_level
reduce_weapon_options if @remaining_possibilities.size > 10 ** 6
if !@remaining_possibilities.kind_of?(Array)
@remaining_possibilities = @remaining_possibilities.to_a
end
guess = @remaining_possibilities.sample
response = @client.solve_level(@current_level.levelNum, guess)
if response['roundsLeft']
reset_remaining_possibilities
return Nil
elsif !response['response']
return response
end
@remaining_possibilities.select! do |possibility|
Game.evaluate(guess, possibility) == response['response']
end
return Nil
end
Run Code Online (Sandbox Code Playgroud)
现在你在 ruby 代码中看到排列的长度在它被转换为数组/散列以继续处理之前被计算,如果数字大于 10**6 则它调用另一个方法“reduce_weapon_options”。虽然在 python 中没有办法在不转换为列表之前获得生成器的长度,但我需要它以这种方式工作,因为此时当我获得更大的范围时,它会卡住并被我的服务器杀死。我无法扩展 ram,因为我需要像 ruby 一样使用更少的 ram,我绝对想避免
self.remaining_possibilities = 列表(self.remaining_possibilities)
如果条件通过/失败,则在python之前。
注意:我正在使用 itertools.permutations 来计算后来保存在“self.remaining_possibilities”中的排列
这是python和ruby中的代码:
return (0...@numWeapons).to_a.permutation(@numGladiators)
(THIS RETURNS AN ENUMERATOR OBJECT)
return it.permutations(range(0, self.numWeapons), self.numGladiators)
(THIS RETURNS A GENERATOR OBJECT)
Run Code Online (Sandbox Code Playgroud)
解决这个问题的最简单方法可能是使用排列公式计算生成的排列数,可以定义为:
from math import factorial
def nPr(n, r):
return int(factorial(n)/factorial(n-r))
Run Code Online (Sandbox Code Playgroud)
但是,这要求此数据可用或长度从创建原始排列生成器的位置传递。如果不是这种情况,出于某种原因,可以使用itertools.tee()从第一个生成器生成第二个生成器,并将其仅用于计数:
def solve_current_level(self):
self.remaining_possibilities, perm_count = itertools.tee(self.remaining_possibilities)
# exhausting the 'teed' generator, leaving the 'original' intact:
num_perm = sum(1 for _ in perm_count)
if num_perm > 10 ** 6:
#self.reduce_weapon_options()
pass
# here we can still use self.remaining_possibilities
.
.
.
Run Code Online (Sandbox Code Playgroud)
由于您已经在使用itertools这不是一个太重的解决方案,我猜,但它仍然需要您浏览整个列表。不过,内存占用要小得多。