我有文本数据,我试图清理数值。我把它分成尽可能干净的行,并将行分成数据点。一个例子是
["1.115","","","4.3"]
我的代码应该将其转换为
["1.115","4.3"]
以下是摘录:
for i in t:
try:
print(float(i))
except ValueError:
print(i)
t.remove(i)
continue
所有print()语句都用于调试。运行代码给出了
["1.115","","4.3"]
作为输出。如果一行中没有两个非浮点数,它运行正常,但在通过异常处理删除非浮点数后,它不会打印下一个浮点值。
答案 0 :(得分:2)
这看起来像是修改当前正在循环的列表的问题 - 通过删除元素,您已经更改了临时偏移的含义。一个解决方法是创建一个新列表而不是更改原始列表:
t = ["1.115", "", "", "4.3"]
s = []
for i in t:
try:
s.append(float(i))
except ValueError:
pass
print(s)
如果你真的想要循环来修改原始列表,你可以尝试这样的事情:
t = ["1.115", "", "", "4.3"]
i = 0
while i < len(t):
try:
float(t[i])
i += 1
except ValueError:
del t[i]
print(t)
但请确保您已经考虑了所有可能的情况并进行了彻底的测试。
答案 1 :(得分:1)
此代码成为该问题的牺牲品,因为您正在修改您正在迭代的相同列表。构造作为输出的新列表更常见。这是一个例子:
def yield_only_floats(l):
for s in l:
try:
float(s)
yield s
except ValueError:
pass
x = list(yield_only_floats(["1.115","","","4.3"]))
print x
获取[&#39; 1.115&#39;,&#39; 4.3&#39;]
的结果如果您想修改原始列表,您仍然可以这样做:
x = ["1.115","","","4.3"]
x[:] = list(yield_only_floats(x))
但是,如果你真的想修改迭代时迭代的同一个列表,最好的想法是反向迭代:
def leave_only_floats(l):
for i in xrange(len(l) - 1, -1, -1):
try:
float(l[i])
except ValueError:
del l[i]
x = ["1.115","","","4.3"]
leave_only_floats(x)
请注意,我还使用了位置删除,而不是值删除,这使得它更快(列表不必再次搜索)
顺便说一下,你也可以考虑使用列表理解:def is_float(s):
try:
float(s)
return True
except ValueError:
return False
x = ["1.115","","","4.3"]
y = [s for s in x if is_float(s)]
就我个人而言,我觉得列表理解方法对于这类问题最具可读性。
答案 2 :(得分:1)
改变你正在迭代的对象并不是一个好主意。列表迭代是按索引完成的,因此当您擦除一个元素时,右侧的剩余元素将向下移动。
t = ["1.115", "", "", "4.3"]
for i in t:
try:
print(float(i))
except ValueError:
print(i)
t.remove(i)
# First run of loop:
idx = 0
i = "1.115"
t = ["1.115", "", "", "4.3"]
# Second run of loop
idx = 1
i = ""
t = ["1.115", "", "4.3"]
# Third, last run of loop
idx = 2
i = "4.3"
t = ["1.115", "", "4.3"]
正确的做法:
t = ["1.115","","","4.3"]
def is_float(number):
try:
float(number)
return True
except ValueError:
return False
res = list(filter(is_float, t))
答案 3 :(得分:0)
只需将.copy()添加到循环中并删除'continue'语句:
for i in t.copy():
try:
print(float(i))
except ValueError:
print(i)
t.remove(i)