Python- 如何更新遍历文件行的 for 循环的索引?
Python- How do I update an index of a for loop that iterates over lines in a file?
我使用 for 循环遍历文件中的行。给定这一行:
line= [ ‘641', '"Tornadus', ' (Incarnate Form)"', '"Flying"', '""', '5', '"TRUE"']
我需要将索引 [6] 从“"TRUE"”重新格式化为布尔值 True。
完整的预期输出:d={'Tornadus, (Incarnate Form)': (641, 'Flying', None, 5, True}
我用过:
if "T" in line[6]: # format legendary if TRUE
line[6] = True
但是我得到这个错误:
Traceback (most recent call last):
File "tester5p.py", line 305, in test_read_info_file_05
self.assertEqual(read_info_file(DATAFILE),info_db5())File "/Users/kgreenwo/Desktop/student.py", line 52, in read_info_file
line[5] = False
TypeError: 'str' object does not support item assignment
如何在 for 循环中分配它?
查看我的完整代码:
def read_info_file(filename):
f = open(filename, 'r') # open file in read mode
d = {} # intitialze as empty
count = 0 # helps to skip first line
key = ""
for line in f: # get each line from file
if count != 0: # skip first line
# 1___________________________________________open file,read, skip 1st line
id_num = int(line[0]) # make id an integer
# 2________________________________________________
if ',' in line[1]: # two parts to fullname, changes indexes
part1 = line[1].strip('"') # get format first part of name
part2 = line[2].strip() # get format second part of name
# 3______________
fullname = part1 + part2
key = fullname
# 4______________
type1 = line[3].strip('"')
# 5--------------
if line[4] == "": # check if there is not a second type
type2 = None # correct format
else: # is a second type
type2 = line[4].strip('"') # format second type
# 6______________
generation = line[5] # format generation
# 7_____________
if "T" in line[6]: # format legendary if TRUE
line[6] = True
legendary = line[6]
else: # format legendary if FALSE
line[6] = False
legendary = line[6]
# 8______________________________________________one part to name
else: # one part to name
fullname = line[1].strip('"')
# 9______________
type1 = line[2].strip('"')
# 10_____________
if line[3] == "": # if no second type
type2 = None
else:
type2 = line[3].strip('"') # there is a second type
# 11_____________
generation = line[4] # format generation
# 12_____________
if "T" in line[5]: # format legendary if TRUE
line[5] = True
legendary = line[5]
else: # formmat Legendary if False
line[5] = False
legendary = line[5]
value = (id_num, type1, type2, generation, legendary)
d.update([(key, value)])
count += 1
return d
Reproducible example:
input: (don't forget to skip first line!)
info_file1 = '''"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
Output:
d={'Bulbasaur':(1,'Grass','Poison',1,False)}
从你的例子中看不太清楚,但我的想法是:
for line in f:
line = line.split(',')
现在你可以弄乱索引,看看你是否有更多的错误。
如果你使用:
if "T" in line[6]: # format legendary if TRUE
line[6] = True
它会起作用。
我没有重新分配它,而是这样做了并且成功了:
if "T" in line[6]: # format legendary if TRUE
legendary = True
else: # format legendary if FALSE
legendary = False
您的输入文件看起来像 comma-separated values 文件。如果是,你想要的就很简单了。
假设您的输入文件是这样的:
Input_file-43644346.txt
info_file1 = '''"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
641,"Tornadus', ' (Incarnate Form)","Flying",,5,"TRUE"
你可以这样做:
#!/usr/bin/env python3
import csv
input_file_name = "Input_file-43644346.txt"
with open(input_file_name, newline='') as input_file:
next(input_file) # skip first line
record_extractor = csv.reader(input_file)
d = {}
for row in record_extractor:
key = row[1].strip()
row_truth = row[5] == "TRUE" # simplifying the boolean retrieving
# Using conditional expressions
row_second_type = row[3].strip() if row[3] else None
output_row = (row[0], row[2], row_second_type, row[4], row_truth)
d[key] = output_row
print("d=", d)
以下是此解决方案的一些要点:
- 此示例采用 Python 3 的语法
- 使用
with
确保及时关闭输入文件
- 由于文件对象也是一个迭代器,您可以使用
next()
. 跳过第一行
csv.reader()
会给你一个包含一行信息的元组。它会像您期望的那样处理带引号的字符串。
- 表达式
row[5] == "TRUE"
将产生一个布尔表达式。您不需要使用 if
语句。
- 空字符串等同于 False。任何其他字符串为真。
- Conditional expressions 可用于将空字符串更改为您想要的
None
。
dict.update()
如果您已经有了字典或元组列表,您希望使用它的值来更新字典,但您最好使用 d[key] = value
但我的猜测是您的文件更像这样:
Input_file-43644346b.txt
"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
641,"Tornadus', ' (Incarnate Form)","Flying",,5,"TRUE"
然后您可以使用 csv.DictReader
读取您的数据:
#!/usr/bin/env python3
import csv
input_file_name = "Input_file-43644346b.txt"
with open(input_file_name, newline='') as input_file:
record_extractor = csv.DictReader(input_file)
d = {}
for row in record_extractor:
key = row["Name"].strip()
row_truth = row["Legendary"] == "TRUE"
row_second_type = row["Type 2"].strip() if row["Type 2"] else None
output_row = (row["ID"], row["Type 1"],
row_second_type, row["Generation"], row_truth)
d[key] = output_row
print("d=", d)
这使您能够使用 "column" 名称来标识每一行的不同部分
您可以使用 dictionary 理解来进一步简化您的代码:
#!/usr/bin/env python3
import csv
input_file_name = "Input_file-43644346.txt"
with open(input_file_name, newline='') as input_file:
next(input_file) # skip first line
record_extractor = csv.reader(input_file)
d = { row[1]: (row[0],
row[2],
row[3].strip() if row[3] else None,
row[4],
row[5] == "TRUE")
for row in record_extractor }
print("d=", d)
我使用 for 循环遍历文件中的行。给定这一行:
line= [ ‘641', '"Tornadus', ' (Incarnate Form)"', '"Flying"', '""', '5', '"TRUE"']
我需要将索引 [6] 从“"TRUE"”重新格式化为布尔值 True。
完整的预期输出:d={'Tornadus, (Incarnate Form)': (641, 'Flying', None, 5, True}
我用过:
if "T" in line[6]: # format legendary if TRUE
line[6] = True
但是我得到这个错误:
Traceback (most recent call last): File "tester5p.py", line 305, in test_read_info_file_05 self.assertEqual(read_info_file(DATAFILE),info_db5())File "/Users/kgreenwo/Desktop/student.py", line 52, in read_info_file line[5] = False
TypeError: 'str' object does not support item assignment
如何在 for 循环中分配它?
查看我的完整代码:
def read_info_file(filename):
f = open(filename, 'r') # open file in read mode
d = {} # intitialze as empty
count = 0 # helps to skip first line
key = ""
for line in f: # get each line from file
if count != 0: # skip first line
# 1___________________________________________open file,read, skip 1st line
id_num = int(line[0]) # make id an integer
# 2________________________________________________
if ',' in line[1]: # two parts to fullname, changes indexes
part1 = line[1].strip('"') # get format first part of name
part2 = line[2].strip() # get format second part of name
# 3______________
fullname = part1 + part2
key = fullname
# 4______________
type1 = line[3].strip('"')
# 5--------------
if line[4] == "": # check if there is not a second type
type2 = None # correct format
else: # is a second type
type2 = line[4].strip('"') # format second type
# 6______________
generation = line[5] # format generation
# 7_____________
if "T" in line[6]: # format legendary if TRUE
line[6] = True
legendary = line[6]
else: # format legendary if FALSE
line[6] = False
legendary = line[6]
# 8______________________________________________one part to name
else: # one part to name
fullname = line[1].strip('"')
# 9______________
type1 = line[2].strip('"')
# 10_____________
if line[3] == "": # if no second type
type2 = None
else:
type2 = line[3].strip('"') # there is a second type
# 11_____________
generation = line[4] # format generation
# 12_____________
if "T" in line[5]: # format legendary if TRUE
line[5] = True
legendary = line[5]
else: # formmat Legendary if False
line[5] = False
legendary = line[5]
value = (id_num, type1, type2, generation, legendary)
d.update([(key, value)])
count += 1
return d
Reproducible example: input: (don't forget to skip first line!)
info_file1 = '''"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
Output: d={'Bulbasaur':(1,'Grass','Poison',1,False)}
从你的例子中看不太清楚,但我的想法是:
for line in f:
line = line.split(',')
现在你可以弄乱索引,看看你是否有更多的错误。 如果你使用:
if "T" in line[6]: # format legendary if TRUE
line[6] = True
它会起作用。
我没有重新分配它,而是这样做了并且成功了:
if "T" in line[6]: # format legendary if TRUE
legendary = True
else: # format legendary if FALSE
legendary = False
您的输入文件看起来像 comma-separated values 文件。如果是,你想要的就很简单了。
假设您的输入文件是这样的:
Input_file-43644346.txt
info_file1 = '''"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
641,"Tornadus', ' (Incarnate Form)","Flying",,5,"TRUE"
你可以这样做:
#!/usr/bin/env python3
import csv
input_file_name = "Input_file-43644346.txt"
with open(input_file_name, newline='') as input_file:
next(input_file) # skip first line
record_extractor = csv.reader(input_file)
d = {}
for row in record_extractor:
key = row[1].strip()
row_truth = row[5] == "TRUE" # simplifying the boolean retrieving
# Using conditional expressions
row_second_type = row[3].strip() if row[3] else None
output_row = (row[0], row[2], row_second_type, row[4], row_truth)
d[key] = output_row
print("d=", d)
以下是此解决方案的一些要点:
- 此示例采用 Python 3 的语法
- 使用
with
确保及时关闭输入文件 - 由于文件对象也是一个迭代器,您可以使用
next()
. 跳过第一行
csv.reader()
会给你一个包含一行信息的元组。它会像您期望的那样处理带引号的字符串。- 表达式
row[5] == "TRUE"
将产生一个布尔表达式。您不需要使用if
语句。 - 空字符串等同于 False。任何其他字符串为真。
- Conditional expressions 可用于将空字符串更改为您想要的
None
。 dict.update()
如果您已经有了字典或元组列表,您希望使用它的值来更新字典,但您最好使用d[key] = value
但我的猜测是您的文件更像这样:
Input_file-43644346b.txt
"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
641,"Tornadus', ' (Incarnate Form)","Flying",,5,"TRUE"
然后您可以使用 csv.DictReader
读取您的数据:
#!/usr/bin/env python3
import csv
input_file_name = "Input_file-43644346b.txt"
with open(input_file_name, newline='') as input_file:
record_extractor = csv.DictReader(input_file)
d = {}
for row in record_extractor:
key = row["Name"].strip()
row_truth = row["Legendary"] == "TRUE"
row_second_type = row["Type 2"].strip() if row["Type 2"] else None
output_row = (row["ID"], row["Type 1"],
row_second_type, row["Generation"], row_truth)
d[key] = output_row
print("d=", d)
这使您能够使用 "column" 名称来标识每一行的不同部分
您可以使用 dictionary 理解来进一步简化您的代码:
#!/usr/bin/env python3
import csv
input_file_name = "Input_file-43644346.txt"
with open(input_file_name, newline='') as input_file:
next(input_file) # skip first line
record_extractor = csv.reader(input_file)
d = { row[1]: (row[0],
row[2],
row[3].strip() if row[3] else None,
row[4],
row[5] == "TRUE")
for row in record_extractor }
print("d=", d)