试图浏览大型列表时的Python索引器
我有一个大约200000多个对象的列表,每个对象代表一个文件(但实际上并不包含文件的内容,只包含完整的路径名和日期) 我正在编写的程序会复制这些文件的任何子集,具体取决于用户提供的日期范围。我首先创建源目录中所有文件的列表(使用试图浏览大型列表时的Python索引器,python,Python,我有一个大约200000多个对象的列表,每个对象代表一个文件(但实际上并不包含文件的内容,只包含完整的路径名和日期) 我正在编写的程序会复制这些文件的任何子集,具体取决于用户提供的日期范围。我首先创建源目录中所有文件的列表(使用glob模块),创建我的文件表示类的实例并将该实例添加到列表中,如下所示: for f in glob.glob(srcdir + "/*.txt"): LOG_FILES.append(LogFile(f)) 现在,为了快速复制文件并保持代码块干净,我删除了不
glob
模块),创建我的文件表示类的实例并将该实例添加到列表中,如下所示:
for f in glob.glob(srcdir + "/*.txt"):
LOG_FILES.append(LogFile(f))
现在,为了快速复制文件并保持代码块干净,我删除了不在日期范围内的日志文件对象
for i in xrange(0, len(LOG_FILES)):
if LOG_FILES[i].DATE < from_date or LOG_FILES[i].DATE > to_date:
del(LOG_FILES[i])
xrange中i的出现问题…
示例:当i
的值达到63792时,我被抛出一个索引器
IndexError: list index out of range.
有什么想法吗
编辑非常感谢您的快速回复!现在我想起来了,这是我一个愚蠢的疏忽。再次感谢大家。:) [EDIT]哎呀,我忘了反转“”并添加一个等号
LOG_FILES = [LogFile(f) for f in glob.glob(srcdir + "/*.txt")
if from_date <= f.DATE <= to_date]
LOG_FILES=[glob.glob(srcdir+“/*.txt)”中f的日志文件(f)
如果from_date如果您在一个具有固定上限的数组上循环,同时删除元素,则将生成索引错误。您必须循环一个副本或使用动态索引。由于您声明数组很大,我们使用后者:
limit, i = len(LOG_FILES), 0
while i < limit:
if LOG_FILES[i].DATE < from_date and LOG_FILES[i].DATE > to_date:
del(LOG_FILES[i])
limit -= 1
else:
i += 1
limit,i=len(日志文件),0
而我认为:
如果日志文件[i].DATE<自日志文件[i].DATE>至日志文件[i].DATE]:
del(日志文件[i])
限制-=1
其他:
i+=1
来自:
在循环中修改正在迭代的序列是不安全的(这只能发生在可变序列类型上,如列表)。如果需要修改正在迭代的列表(例如,复制选定项),则必须在副本上迭代
对于您的情况,我实际上建议您考虑使用生成器表达式和,以避免对您的大文件列表进行不必要的复制。您的方法的问题是删除列表中该索引处的条目并重新排序列表
例如,如果列表中有五个项目,并在第三个索引上调用del(),则列表的内容将下移,以便另一个元素使用第三个索引
list = [1,2,3,4,5]
del(list[2])
print list # outputs [1, 2, 4, 5]
print list[2] # outputs 4
由于您正在从0循环到列表的原始大小,因此即使您仅从列表中删除了一项,最终也会得到不再包含在列表中的索引
一种更简单的方法是在向列表中添加项目时对列表进行过滤
for f in glob.glob(srcdir + "/*.txt"):
lf = LogFile(f)
if lf.DATE < from_date and lf.DATE > to_date:
LOG_FILES.append(lf)
glob.glob(srcdir+“/*.txt”)中的f的
lf=日志文件(f)
如果lf.DATEto_DATE:
日志文件。附加(lf)
这可能会变得更具python风格,但应该足够可读,以便理解这一点。您还可以使用:
LOG\u FILES=filter(lambda LOG\u file:LOG\u file.DATE截止日期,日志文件)
1)在列表的迭代过程中从列表的末尾到开头删除元素解决问题
LOG_FILES = [ 1,2,30,2,5,8,30,3,2,37,22,30,27,30,4 ]
print LOG_FILES
L = len(LOG_FILES)-1
for i,x in enumerate(LOG_FILES[::-1]):
print i,L-i,' ',LOG_FILES[L-i],x
if x>15:
del LOG_FILES[L-i]
print LOG_FILES
结果
[1, 2, 30, 2, 5, 8, 30, 3, 2, 37, 22, 30, 27, 30, 4]
0 14 4 4
1 13 30 30
2 12 27 27
3 11 30 30
4 10 22 22
5 9 37 37
6 8 2 2
7 7 3 3
8 6 30 30
9 5 8 8
10 4 5 5
11 3 2 2
12 2 30 30
13 1 2 2
14 0 1 1
[1, 2, 2, 5, 8, 3, 2, 4]
2) 顺便说一下
if LOG_FILES[i].DATE < to_date and LOG_FILES[i].DATE > from_date :
如果日志文件[i].DATE开始日期:
可以写
if from_date < LOG_FILES[i].DATE < to_date:
如果从日期<日志文件[i]。日期<到日期:
Cpfohl的答案中有一个问题:
LOG_FILES = [LogFile(f) for f in glob.glob(srcdir + "/*.txt")
if f.DATE >= from_date and f.DATE <= to_date]
因此,日志文件[i]是日志文件(f)
然后是一个日志文件[i]。日期是一个日志文件(f).DATE,而不是f.DATE您正在修改要迭代的序列。日期范围在SQL中很容易查询。如果应用程序是为了分发给用户,也许数据库是最好的。这只是一个想法。谢谢krs,但它不是为了分发-它只是从我们正在运行的古老系统中获取一组日志文件(我最终会重写)这会创建特定事件的日志。我发布了两个关于您的problem@eyquem:谢谢-我在实现Cpfohl的示例时修改了它;我没有直接使用它。我会发布我所做的,但我手头没有代码来发布有效的内容。这里引用的文档评论是正确的,但我认为更好的解释是国家将包括为什么它不是安全的你是正确的,你的答案是一个很好的解释,+ 1。谢谢!谢谢你指出。当我从C++或C语言转换成Python……时,我总是丢失这一块:)你也可以使用<代码> GOLB.IGLB < /C> >避免创建不必要的列表。
if from_date < LOG_FILES[i].DATE < to_date:
LOG_FILES = [LogFile(f) for f in glob.glob(srcdir + "/*.txt")
if f.DATE >= from_date and f.DATE <= to_date]
for f in glob.glob(srcdir + "/*.txt"):
LOG_FILES.append(LogFile(f))