Python 加快元组计数
对于我正在做的项目,我感兴趣的是创建一个符合以下条件的所有元组(I、j、k、z、f)的列表:Python 加快元组计数,python,performance,for-loop,counting,Python,Performance,For Loop,Counting,对于我正在做的项目,我感兴趣的是创建一个符合以下条件的所有元组(I、j、k、z、f)的列表: 所有五个变量都可以在0到343之间变化 i==k或j==z或k==f 到目前为止,我得出的结论是: z1=set() for i in xrange(344): for j in xrange(344): for k in xrange(344): for z in xrange(344): for f in xrang
- 所有五个变量都可以在0到343之间变化
- i==k或j==z或k==f
z1=set()
for i in xrange(344):
for j in xrange(344):
for k in xrange(344):
for z in xrange(344):
for f in xrange(344):
if f!=k:
continue
z1.add((i,j,k,z,f))
for i in xrange(344):
for j in xrange(344):
for k in xrange(344):
for z in xrange(344):
for f in xrange(344):
if z!=j:
continue
if (i,j,k,z,f) not in z1:
z1.add((i,j,k,z,f))
for i in xrange(344):
for j in xrange(344):
for k in xrange(344):
for z in xrange(344):
for f in xrange(344):
if k!=i:
continue
if (i,j,k,z,f) not in z1:
z1.add((i,j,k,z,f))
这很慢。我在想也许有一个简单的方法来加速这一点,我忽略了。。。有什么想法吗?也许你想少循环,少比较 尝试以下操作,可能会更快:
def doit ():
theRange = range (343)
for i in theRange:
for j in theRange:
for k in theRange:
cond1 = i == k
for z in theRange:
cond2 = j == z
for f in theRange:
if cond1 or cond2 or k == f:
yield i, j, k, z, f
for x in doit ():
doSomethingWith (x)
您可能希望减少循环和比较 尝试以下操作,可能会更快:
def doit ():
theRange = range (343)
for i in theRange:
for j in theRange:
for k in theRange:
cond1 = i == k
for z in theRange:
cond2 = j == z
for f in theRange:
if cond1 or cond2 or k == f:
yield i, j, k, z, f
for x in doit ():
doSomethingWith (x)
你需要更多的记忆。很多很多的记忆。让我们看看第一个条件,
i==k
。满足该条件的元组数为343**4=13841287201
。130亿!如果每个元组只需要5*4=20
字节的内存,那么这个集合仍然需要257GB的内存。这甚至不是你想要的所有元素
所以,不,没有简单的出路。如果我要将这个问题优化到一个可管理的规模,我首先要问mysqlf:我真的需要这么大的列表吗?或者我可以不用它来解决这个问题吗?您需要更多内存。很多很多的记忆。让我们看看第一个条件,
i==k
。满足该条件的元组数为343**4=13841287201
。130亿!如果每个元组只需要5*4=20
字节的内存,那么这个集合仍然需要257GB的内存。这甚至不是你想要的所有元素
所以,不,没有简单的出路。如果我要将这个问题优化到一个可管理的规模,我首先要问mysqlf:我真的需要这么大的列表吗?或者我可以不使用它来解决这个问题吗?由于您试图构造集合时内存不足,请使用生成器对它们进行迭代,而不将它们全部存储:
itertools.ifilter(
lambda x: x[0] == x[2] or x[1] == x[3] or x[2] == x[4],
itertools.product(xrange(344), repeat=5)
)
当然,迭代仍然需要很长时间,因为还有很多事情要做(大约5万亿个值)。稍后再谈
如果你真的因为某种特殊的原因需要这个集合,你可以基于这个想法来定义一个“懒惰的”不可变集合。在Python 2中:
class MyCollection(collections.Set):
def __contains__(self, x):
if not isinstance(x, tuple): return False
if not len(x) == 5: return False
if not all(isinstance(y, int) for y in x): return False
if not all(0 <= y <= 343 for y in x): return False
return self.match(x)
@classmethod
def match(cls, x):
return (x[0] == x[2] or x[1] == x[3] or x[2] == x[4])
def __iter__(self):
return itertools.ifilter(
self.match,
itertools.product(xrange(344), repeat=5)
)
def __len__(self):
# um. Left as an exercise for the reader. About 39 billion or so.
z1 = MyCollection()
class MyCollection(collections.Set):
def___;包含______;(self,x):
如果不是isinstance(x,tuple):返回False
如果不是len(x)==5:返回False
如果不是全部(x中y的isinstance(y,int):返回False
如果不是全部(0,因为尝试构造集合时会耗尽内存,请使用生成器对它们进行迭代,而不将它们全部存储:
itertools.ifilter(
lambda x: x[0] == x[2] or x[1] == x[3] or x[2] == x[4],
itertools.product(xrange(344), repeat=5)
)
当然,迭代仍然需要很长的时间,因为还有很多事情要做(大约5万亿个值)。稍后将详细介绍
如果出于某种特殊原因确实需要此集合,可以基于此思想定义一个“惰性”不可变集合。在Python 2中:
class MyCollection(collections.Set):
def __contains__(self, x):
if not isinstance(x, tuple): return False
if not len(x) == 5: return False
if not all(isinstance(y, int) for y in x): return False
if not all(0 <= y <= 343 for y in x): return False
return self.match(x)
@classmethod
def match(cls, x):
return (x[0] == x[2] or x[1] == x[3] or x[2] == x[4])
def __iter__(self):
return itertools.ifilter(
self.match,
itertools.product(xrange(344), repeat=5)
)
def __len__(self):
# um. Left as an exercise for the reader. About 39 billion or so.
z1 = MyCollection()
class MyCollection(collections.Set):
def___;包含______;(self,x):
如果不是isinstance(x,tuple):返回False
如果不是len(x)==5:返回False
如果不是全部(x中y的isinstance(y,int):返回False
如果不是全部(0对@Hyboreus的代码稍作调整:
def legal_tuples():
r = range(344)
for i in r:
for j in r:
for k in r:
i_eq_k = i == k
for z in r:
if i_eq_k or j == z:
for f in r:
yield i,j,k,z,f
else:
yield i,j,k,z,k
对@Hyboreus的代码稍加修改:
def legal_tuples():
r = range(344)
for i in r:
for j in r:
for k in r:
i_eq_k = i == k
for z in r:
if i_eq_k or j == z:
for f in r:
yield i,j,k,z,f
else:
yield i,j,k,z,k
你真的不需要条件来做这件事
利用仅包含每个值中一个值的集合
a = set()
for index in xrange(344):
for i in xrange(344):
for j in xrange(344):
for k in xrange(344):
#i==k
a.add((index,i,index,j,k))
#j==z
a.add((i,index,j,index,k))
#k==f
a.add((i,j,index,k,index))
编辑将值类型更改为值~我需要更多的咖啡你真的不需要条件来这样做
利用仅包含每个值中一个值的集合
a = set()
for index in xrange(344):
for i in xrange(344):
for j in xrange(344):
for k in xrange(344):
#i==k
a.add((index,i,index,j,k))
#j==z
a.add((i,index,j,index,k))
#k==f
a.add((i,j,index,k,index))
编辑将值类型更改为值~我需要更多的咖啡这不起作用。我有点搞不清楚为什么不起作用,但例如,如果按这种方式计算范围(5)的元组你得到25个,但如果你按照我的方式,每个大循环只使用一个条件,你得到1525个。@adamlevin在py2和py3上都有限制5,这个代码段产生1525个值。@adamlevin python 2.7.5+和python3.2.4是准确的。你是对的,它确实产生1525个,但它们似乎与用我的代码创建的不匹配。我可能犯了一个错误。l让我看看其他的回答,我会回来的。@adamlevin您的顺序不同,仅此而已。这不起作用。我有点困惑,为什么它不起作用,但例如,如果您以这种方式计算范围(5)的元组你得到25个,但如果你按照我的方式,每个大循环只使用一个条件,你得到1525个。@adamlevin在py2和py3上都有限制5,这个代码段产生1525个值。@adamlevin python 2.7.5+和python3.2.4是准确的。你是对的,它确实产生1525个,但它们似乎与用我的代码创建的不匹配。我可能犯了一个错误。l让我看看其他的回答,我会回来的。@adamlevin您的顺序不同,仅此而已。+1可能您需要在func定义后面加括号。我认为列表(范围(344))
即使在py3中也是不必要的,因为你总是要开始新的迭代。哈哈。我对我的代码也有同样的怀疑,我刚刚通过…尝试了解了这个细节,没有错误。+1也许你想要func定义后面的括号。我想列表(范围(344))
即使在py3中也是不必要的,因为你总是要开始新的迭代。哈哈。我对我的代码也有同样的怀疑,我刚刚通过……尝试而不是错误地了解了这个细节。你的问题标题是“元组计数”但是,你的代码试图实现一个大的列表。你真正需要做什么?我想要一个tuple列表,它可能想考虑其他的东西,然后。^ ^)你的问题标题是指“元组的计数”。但是,你的代码试图实现一个大的列表。你真正需要做什么?我想要一个tuple列表,可能想考虑其他的东西,然后。