Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 访问循环中最后一次迭代的值的最佳方式_Python_Loops - Fatal编程技术网

Python 访问循环中最后一次迭代的值的最佳方式

Python 访问循环中最后一次迭代的值的最佳方式,python,loops,Python,Loops,假设对象非常大(例如,有100000多条记录的游标对象),那么访问for循环中上一次迭代中的值的最佳和最快方法是什么 举一个简单的例子: tmp = [ ['xyz', 335], ['zzz', 338], ['yyy', 339], ['yyy', 442], ['abc', 443], ['efg', 444], ['ttt', 446], ['fff', 447] ] for x in tmp: if not prev:

假设对象非常大(例如,有100000多条记录的游标对象),那么访问for循环中上一次迭代中的值的最佳和最快方法是什么

举一个简单的例子:

tmp = [
         ['xyz', 335], ['zzz', 338], ['yyy', 339], ['yyy', 442], 
         ['abc', 443], ['efg', 444], ['ttt', 446], ['fff', 447]
      ]

for x in tmp:
   if not prev:
     prev = x[1]
   print 'seq: ', x[1], 'prev seq:', prev, 'variance: ', x[1]-prev
   prev = x[1]
这是处理这个问题的最佳方式吗

根据下面的回答,我做了一些测试: tmp由500个列表创建,平均运行20次如下所示

结果:

矿山:0623
戴夫:1:0605
戴夫:2:0586

Catchmeifyoutry(已编辑代码):0707

您的代码将在循环中的每一次执行“if not prev”测试,即使它仅适用于第一个元素。 另外,我觉得你的代码似乎有问题——第一次循环时,prev和current的值是相同的

我会这样做,假设至少有一个元素:

tmp_iter = iter(tmp)
prev = tmp_iter.next()

for x in tmp_iter: 
   print 'seq: ', x[1], 'prev seq:', prev[1], 'variance: ', x[1]-prev[1]
   prev = x
这可以通过取消索引进一步优化:

tmp_iter = iter(tmp)
[_, prev] = tmp_iter.next()

for [_, x] in tmp_iter: 
   print 'seq: ', x, 'prev seq:', prev, 'variance: ', x-prev
   prev = x

我使用赋值将列表划分为其组成部分,并将第一个元素赋值给u,因为它未被使用。

此代码生成NameError,因为在
如果不是prev
,则未定义prev。在循环之前将其设置为False或None。此外,您还可以进行不同的循环:

for i in xrange(1, len(tmp)):
    print 'seq: {0}, prev seq: {1}, variance: {2}'.format(tmp[i][1], tmp[i - 1][1], tmp[i] - tmp[i - 1][1])
如果你要使用100000多条记录,瓶颈将不是周期,而是应用程序使用的内存。不要以这样的格式存储所有数据:每对值(一个列表)。如果它们在一个文件中,最好对其行进行迭代:

(假设数据以制表符分隔)

reader
是一个函数,它多次返回序列中的值。这样,在任何时候内存中只会存储2行数据,你的应用程序甚至可以支持数百万行


为了使代码具有可读性,我将其放在一边,以便在程序体中处理数据序列,而不考虑其组成方式。

只需使用可读性更高的
zip()
对数据序列进行迭代即可

更新:对于Python2.x,请改用
itertools.izip
,因为它更高效

from itertools import izip
for prev, next in izip(tmp, tmp[1:]):
    print 'seq: ', next[1], 'prev seq:', prev[1], 'variance: ', next[1]-prev[1]
也可以使用值解包来避免索引:

for (_, prev), (_, next) in izip(tmp, tmp[1:]):
    print 'seq: ', next, 'prev seq:', prev, 'variance: ', next-prev
或者,如果你真的需要第一次迭代

for prev, next in izip(tmp, tmp[:1] + tmp):
    print 'seq: ', next[1], 'prev seq:', prev[1], 'variance: ', next[1]-prev[1]
编辑

如果要避免在第二个参数中创建列表,还可以使用显式迭代器:

itr = iter(tmp)
itr.next() # here I assume tmp is not empty, otherwise an exception will be thrown
for prev, next in izip(tmp, itr):
    print 'seq: ', next[1], 'prev seq:', prev[1], 'variance: ', next[1]-prev[1]
注意:此zip模式在类似问题中也很有用。 例如,要从列表中提取连续的三元组:

xs = range(9)
triplets = zip(xs[::3], xs[1::3], xs[2::3]) # python 2.x, zip returns a list

print xs       # [0, 1, 2, 3, 4, 5, 6, 7, 8]
print triplets # [(0, 1, 2), (3, 4, 5), (6, 7, 8)]

还请注意,在中,类似于使用
itertools
itertools.izip:

it = imap(operator.itemgetter(1), tmp) # get all 2nd items
prev = next(it, None) # get 1st element (doesn't throw exception for empty `tmp`)
for x in it:
    print 'seq: %s prev seq: %s variance: %s' % (x, prev, x-prev)
    prev = x
from itertools import izip, islice
for prev, cur in izip(l, islice(l, 1, None)):
    print 'seq:', cur[1], 'prev seq:', prev[1], 'delta:', cur[1]-prev[1]
对于问题中给出的具体示例,请注意,如果 可以使用32位整数表示,并且数字列表适合 内存,计算差异的最快方法之一是 使用
numpy

import numpy
a = numpy.array([x[1] for x in tmp])
delta = numpy.diff(a)

圭多的时间机器来营救

从页面:

这应该是最合适的方法(考虑iterable是
(random.randint(100)表示x范围内的x(1000))
;这里
iter(iterable);next(iterable)
,因为辅助迭代器可能无法提供正确的功能

在循环中使用它作为:

for prev_item, item in pairwise(iterable):
    …

Dave感谢您的快速响应,事实上代码是正确的,在第一次迭代中,方差实际上应该是0,即之前没有任何变化。进一步的优化,例如?这里的第二个选项似乎最快,将使用avg resultsHi culebron更新我的问题,是的,在我的代码中,我确实设置了prev=None(但这里没有包括它)感谢您的回复,刚刚测试了这个(您编辑的代码),并且它似乎是所有选项中最慢的(比上面我的原始代码还要慢),正如前面提到的,这可能是因为zip在python 2.x中在内存中构建了一个完整的列表。无论如何,在这种情况下,您应该使用显式循环。太糟糕了,这是最佳解决方案(在“理想的pythonic方式”的意思)。祝你好运!不要这样,Python2.x有
itertools.izip
:p,请再重复一次另一个注意:使用真正易于使用的
psyco
JIT编译器for python可能会使这些循环受益:有趣,在winxp上网本上使用Python2.5(是的),没有psyco,我的izip解决方案比你的解决方案快,但比Dave的解决方案慢(使用范围(100000)),但是有psyco,你的解决方案比Dave的快得多,然后是Dave的,然后是我的。如果我可以回敬你一句:
上一句:break
是编写的
next(it,None)
现在:)@titΖΖΖIΖΥ:谢谢。因为Python 2.6
next(it,None)
就是这样。
import itertools
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return itertools.izip(a, b)
for prev_item, item in pairwise(iterable):
    …