简体   繁体   English

如何在python中以更有效的方式重写此循环

[英]how to rewrite this loop in a more efficient way in python

I have a loop of the following type: 我有以下类型的循环:

a = range(10)
b = [something]
for i in range(len(a)-1):
    b.append(someFunction(b[-1], a[i], a[i+1]))

However the for-loop is killing a lot of performance. 但是,for循环会破坏很多性能。 I have try to write a windows generator to give me 2 elements everything time but it still require explicit for-loop in the end. 我试图编写一个Windows生成器,以便每次都给我2个元素,但最后仍然需要显式的for循环。 Is there a way to make this shorter and more efficient in a pythonic way? 有没有办法用pythonic方法使它更短,更有效?

Thanks 谢谢

edit: I forgot the element in b.. sorry guys. 编辑:我忘记了b ..对不起,各位。 However the solution to my previous problem is very helpful in other problem I have too. 但是,解决我以前的问题对我遇到的其他问题也很有帮助。 Thanks. 谢谢。

Consider this 考虑一下

def make_b( a, seed ):
    yield seed
    for a,b in zip( a[:-1], a[1:] ):
        seed= someFunction( seed, a, b )
        yield seed

Which lets you do this 这让你做到这一点

a = xrange(10)
b= list(make_b(a,something))

Note that you can often use this: 请注意,您经常可以使用以下命令:

b = make_b(a)

Instead of actually creating b as a list. 而不是实际创建b作为列表。 b as a generator function saves you considerable storage (and some time) because you may not really need a list object in the first place. b作为生成器函数可以节省大量的存储空间(并节省一些时间),因为您可能根本不需要list对象。 Often, you only need something iterable. 通常,您只需要可迭代的内容。

Similarly for a . 同样a It does not have to be a list , merely something iterable -- like a generator function with a yield statement. 它不必是list ,而可以是可迭代的东西,例如带有yield语句的生成器函数。

For your initially stated problem of mapping a function over pairs of an input sequence the following will work, and is about as efficient as it gets while staying in Python land. 对于您最初提出的在输入序列对上映射函数的问题,下面的方法将起作用,并且效率与停留在Python领域中时一样高效。

from itertools import tee

a = range(10)
a1, a2 = tee(a)
a2.next()
b = map(someFunction, a1, a2)

As for the expanded problem where you need to access the result of the previous iteration - this kind of inner state is present in the functional concept unfold. 至于需要访问先前迭代结果的扩展问题-这种内部状态在功能概念中存在。 But Python doesn't include an unfold construct, and for a good reason for loops are more readable in this case and most likely faster too. 但是Python不包含展开结构,因此在这种情况下,循环更具可读性,而且很有可能也更快。 As for making it more Pythonic, I suggest lifting the pairwise iteration out to a function and create an explicit loop variable. 至于使其更具Pythonic性,我建议将成对迭代提升为一个函数并创建一个显式循环变量。

def pairwise(seq):
    a, b = tee(seq)
    b.next()
    return izip(a, b)

def unfold_over_pairwise(unfolder, seq, initial):
    state = initial
    for cur_item, next_item in pairwise(seq):
        state = unfolder(state, cur_item, next_item)
        yield state

b = [something]
b.extend(unfold_over_pairwise(someFunction, a, initial=b[-1]))

If the looping overhead really is a problem, then someFunction must be something really simple. 如果循环开销确实是个问题,那么someFunction必须非常简单。 In that case it probably is best to write the whole loop in a faster language, such as C. 在这种情况下,最好以更快的语言(例如C)编写整个循环。

Some loop or other will always be around, but one possibility that might reduce overhead is: 总是会出现一些循环,但可能会减少开销的一种可能性是:

import itertools

def generate(a, item):
  a1, a2 = itertools.tee(a)
  next(a2)
  for x1, x2 in itertools.izip(a1, a2):
    item = someFunction(item, x1, x2)
    yield item

to be used as: 用作:

b.extend(generate(a, b[-1]))

Try something like this: 尝试这样的事情:

a = range(10)    
b = [something] 

s = len(b)
b+= [0] * (len(a) - 1)
[ b.__setitem__(i, someFunction(b[i-1], a[i-s], a[i-s+1])) for i in range(s, len(b))]

Also: 也:

  • using functions from itertools should be useful also (earlier posts) 使用itertools中的函数也应该有用(之前的帖子)
  • maybe you can rewrite someFunction and use map instead of list comprehension 也许您可以重写someFunction并使用map而不是列表理解

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

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