【问题标题】:Items not being removed from list when list is larger列表较大时未从列表中删除的项目
【发布时间】:2015-10-31 00:00:49
【问题描述】:

我正在解析一个非常大的 CSV 文件。我只对其中的 2 行感兴趣(标题为 Ccy1Ccy2 的行)。

到目前为止,我的方法是解析整个文件,并从列表中删除任何不在“已批准”字段列表中的字段。

我在一个只有 3 行的小示例文件上进行了尝试,它运行良好。 当我解析包含 107 行的真实文件时,剩下的不仅仅是“已批准”字段。

为什么它不删除所有不在列表中的值。

这是我当前的脚本:

import csv
data = csv.reader(open('real_sample.csv'))
fields = data.next()
ccy_fields = ['Ccy1', 'Ccy2']

print 'fields: ' + str(fields)
print 'fields to keep: ' + str(ccy_fields)

for item in fields:
    if str(item) not in ccy_fields:
         fields.remove(item)

print "fields: " + str(fields)

【问题讨论】:

  • 首先,你在 for 循环中的缩进是关闭的。不确定这是否只是复制粘贴错误!
  • 您正在从当前正在迭代的列表中删除项目,这是一种不好的做法。请参阅我的回答 here 了解原因。

标签: python list parsing csv


【解决方案1】:

您正在通过从循环主体中的同一列表中删除项目来修改正在迭代的列表。这就是你的问题的原因。

我建议列表推导是一种更好的方法:

fields = [item for item in fields if item in ccy_fields]

另外,csv模块为每个字段返回string类型的数据,所以不用str()转换。

从正在迭代的列表中删除项目时,您通常会看到紧跟已删除项目的项目将被跳过。当您仅使用 3 列进行测试时,如果 ccy_fields 中有 2 列而没有,则可能会看到正确的结果。当扩展到 100 多个项目时,将跳过符合删除条件的字段。

解决您的问题需要确定要保留的列的索引,然后用于过滤掉其他列:

import csv
ccy_fields = ['Ccy1', 'Ccy2']

with open('real_sample.csv') as f:
    reader = csv.reader(f)
    headers = next(reader)
    indices = [i for i,field in enumerate(headers) if field in ccy_fields]
    data = [[row[i] for i in indices] for row in reader]

在此之后,data 将包含所有只有所需列的行。

【讨论】:

    【解决方案2】:

    您需要先获取列表的副本并对其进行迭代,否则迭代将失败并可能出现意想不到的结果。

    for item in fields:
        if str(item) not in ccy_fields:
            fields.remove(item)    
    #replace by
    fields = [item for item in fields if str(item) in ccy_fields]
    

    相关问题:Remove items from a list while iterating in Python

    【讨论】:

      【解决方案3】:

      您可能需要考虑在读取文件时直接获取所需的字段,而不是获取所有数据然后对其进行修整。例如:

      import csv
      data   = csv.reader(open('real_sample.csv'))
      wanted = []
      
      for line in data:  # loop over the data without reading all of it into memory
          if ('Ccy1' in line or'Ccy2' in line):
              wanted.append(line)  # just keep the data when it matches you criteria
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-20
        • 2021-03-12
        • 2017-04-04
        • 2020-05-27
        • 2016-05-08
        • 2011-03-18
        相关资源
        最近更新 更多