繁体   English   中英

如何加速python循环

[英]How to speed up python loop

我看了几个网站上的几个讨论,但没有一个给我一个解决方案。 这段代码运行时间超过5秒:

for i in xrange(100000000):
  pass

我正在研究整数优化问题,我必须使用O(n log n)算法编辑:一个O(n²/ 4)算法,其中n代表所有矩阵'项,即在下面的代码中, n * m = 10000.因此,对于具有10000个元素的矩阵100 * 100,它将导致近25000000次迭代.... 它的代码可以总结如下:

m = 100
n = 100
for i in xrange(m):
  for j in xrange(n):
    for i2 in xrange(i + 1, m):
      for j2 in xrange(j + 1, n):
        if myarray[i][j] == myarray[i2][j2] and myarray[i2][j] == myarray[i][j2]:
          return [i, j], [i2, j2]

我应该放弃Python并返回Java或C?

我使用Python 2.7并且Psyco不可用。 PyPy不支持Tkinter开箱即用,我正在使用Tkinter。

那么,它们会提高循环速度吗? 还有其他解决方案吗?

不是最漂亮的编码风格,但绝望的时代需要绝望的编码。 尝试将嵌套的嵌套循环转换为一个大的生成器表达式:

try:
    i,j,i2,j2 = ((i,j,i2,j2)
        for i in xrange(m)
          for j in xrange(n)
            for i2 in xrange(i + 1, m)
              for j2 in xrange(j + 1, n)
                if myarray[i][j] == myarray[i2][j2] and 
                    myarray[i2][j] == myarray[i][j2]).next()
    return [i,j],[i2,j2]
except StopIteration:
    return None

更新以使用nextins nextproduct ,以及Py3 range而不是xrange

from itertools import product
match = next(((i,j,i2,j2)
    for i, j in product(range(m), range(n))
        for i2, j2 in product(range(i+1, m), range(j+1, n))
            if myarray[i][j] == myarray[i2][j2] and 
                myarray[i2][j] == myarray[i][j2]), None)
if match is not None:
    i,j,i2,j2 = match
    return [i,j],[i2,j2]
else:
    return None

你仍然可以使用python表示法,并使用Cython项目获得C的速度。 第一步是在C循环中转换循环:它是通过键入循环中使用的所有变量自动完成的:

cdef int m = 100
cdef int n = 100
cdef int i, j, i2, j2
for i in xrange(m):
  for j in xrange(n):
    for i2 in xrange(i + 1, m):
      for j2 in xrange(j + 1, n):

对于下一部分,如果myarray是纯C数组,那么没有丰富的python comparaison或数组访问会更好。 使用你的python数组,你可以通过本机比较来删除丰富的比较(如果你的数组有两倍):

        cdef double a, b, c, d
        a = myarray[i][j]
        b = myarray[i2][j2]
        c = myarray[i2][j]
        d = myarray[i][j2]

        if a == b and c == d:
          return [i, j], [i2, j2]

您可以通过运行cython -a yourfile.pyx来查看优化的进展情况,然后打开yourfile.html generate。 您将看到Cython如何优化您的代码,并消除了Python开销。

很抱歉告诉您,但这不是优化问题。 无论您选择哪种语言或实现,此算法在最差和平均情况下都不是O(n*log n) 您可能想要了解Big-O符号的工作原理并开发出更好的算法。

抱歉生成器expr不起作用。 这是一个不同的方案,首先计算所有类似的值,然后查找矩形组:

from collections import defaultdict
from itertools import permutations
def f3(myarray):
    tally = defaultdict(list)
    for i,row in enumerate(myarray):
        for j,n in enumerate(row):
            tally[n].append((i,j))

    # look for rectangular quads in each list
    for k,v in tally.items():
        for quad in permutations(v,4):
            # sort quad so that we can get rectangle corners 
            quad = sorted(quad)
            (i1,j1),(i2,j2) = quad[0], quad[-1]

            # slice out opposite corners to see if we have a rectangle
            others = quad[1:3]

            if [(i1,j2),(i2,j1)] == others:
                return [i1,j1],[i2,j2]

我在你的代码中看了几遍,如果我把它弄好了,你用两个不同的角标记你的矩形。 我很抱歉,如果我的回答更多是一个澄清你的立场的评论然后是一个真正的答案。

答案 - 部分::如果您正在寻找合适的算法,请考虑扫描线算法。 在@SO中找到了一个“最大矩形解决方案”的例子。

我的问题是,你到底在寻找什么?

  1. 解决for-loop困境的最佳方法
  2. 算法的最佳语言
  3. 一种更快的算法来查找矩形

我还必须指出,保罗和你的解决方案会产生不同的结果,因为保罗认为角落标有相同的值而你假设,角落是通过两个不同的值标记的!

我花时间和自由用一个丑陋的c&p脚本来说明它:它通过创建一个2D字段来比较这两个算法,并用string.lowercase字符填充它并将角转换为大写字符。

from random import choice
from string import lowercase
from collections import defaultdict
from itertools import permutations
from copy import deepcopy

m,n = 20, 20
myarray = [[choice(lowercase) for x in xrange(m)] for y in xrange(n)]

def markcorners(i,j,i2,j2):
    myarray[i][j] = myarray[i][j].upper()
    myarray[i2][j] = myarray[i2][j].upper()
    myarray[i2][j2] = myarray[i2][j2].upper()
    myarray[i][j2] = myarray[i][j2].upper()

def printrect():
    for row in myarray:
        print ''.join(row)
    print '*'*m

def paul_algo():
    tally = defaultdict(list)
    for i,row in enumerate(myarray):
        for j,n in enumerate(row):
            tally[n].append((i,j))

    # look for rectangular quads in each list
    for k,v in tally.items():
        for quad in permutations(v,4):
            # sort quad so that we can get rectangle corners 
            quad = sorted(quad)
            (i1,j1),(i2,j2) = quad[0], quad[-1]

            # slice out opposite corners to see if we have a rectangle
            others = quad[1:3]

            if [(i1,j2),(i2,j1)] == others:
                markcorners(i1,j1,i2,j2)

def xavier_algo():   
    for i in xrange(m):
        for j in xrange(n):
            for i2 in xrange(i + 1, m):
                for j2 in xrange(j + 1, n):
                    if myarray[i][j] == myarray[i2][j2] and myarray[i2][j] == myarray[i][j2]:
                        markcorners(i,j,i2,j2)

savearray = deepcopy(myarray)
printrect()

xavier_algo()
printrect()

myarray = deepcopy(savearray)
paul_algo()
printrect()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM