我正在尝试从列表中删除一些项目,
list1 = ["CCC-C", "CCC-P", "CCC-A-P", "CCC-A-H", "CCC-J", "CCC-S-X"]
new_list = [i for i in list1 if (len(i) == 5 or len(i) == 7 or i[6] != "H")]
除非list1
中的任何项目的长度为5或7,或者其第7个字符为“H”,否则它不应位于new_list
。
但上面的代码包含new_list
中的“CCC-A-H”项目。此外,当检查项目“CCC-C”的i [6]时,它不会给出“IndexError:string index out of range”错误。有什么想法吗?
此致
答案 0 :(得分:2)
Python中的布尔表达式按以下顺序执行:
>>> A() or B()
如果A()返回True,则无需检查B()
>>> A() and B()
如果A()返回False,则无需检查B()
我希望它会给你一些想法。
答案 1 :(得分:2)
这样做:
new_list = [i for i in list1 if len(i)==5 or (len(i)==7 and i[6]!="H")]
这样,您只能获得长度为5(条件len(i)==5
)的项目或长度为7的项目,除非最后一个字符是H
(条件(len(i)==7 and i[6]!="H")
)。
如果字符串的长度为7,则只会评估潜在的IndexError
- 倾向条件i[6]!="H"
,确保您不会收到此错误。
答案 2 :(得分:0)
此外,当检查i [6]项目“CCC-C”时,它不会给出“IndexError:string index out of range”错误。
or
正在短路。如果为条件或条件给出的第一个条件是True
,则它不计算第二个条件,因为无论第二个参数的真值如何,整体评估值仍为True
。
此外,“CCC-A-H”匹配,因为它的长度为7.如果你不希望那些以H结尾的字符串在第7位而不管它们的长度如何,你应该重做你的逻辑表达式:
new_list = [i for i in list1 if (len(i) == 5 or len(i) == 7) and (i[6] != "H")]
答案 3 :(得分:0)
正如其他人所指出的那样,len("CCC-A-H") == 7
和python对布尔运算采用短路评估。最终结果是:
(len("CCC-A-H") == 5 or len("CCC-A-H") == 7 or "CCC-A-H"[6] != "H")
将返回true,因为len("CCC-A-H") == 7
在评估"CCC-A-H"[6] != "H"
之前评估为true。
使用filter(...)
函数而不是列表解析可能更容易看到:
list1 = ["CCC-C", "CCC-P", "CCC-A-P", "CCC-A-H", "CCC-J", "CCC-S-X"]
def len57notHWrong(item):
return len(item) == 5 or len(item) == 7 or item[6] != "H"
print "Wrong : ", filter(len57notHWrong, list1)
这是您使用filter(...)
函数的列表理解的简单直接翻译。
如果我们使用if ... elif ... else
构造重写它,它看起来像这样:
def len57notHWrongExpanded(item):
if len(item) == 5: # first check if length is 5
return True
elif len(item) == 7: # now check if length is 7
return True # it's 7? Short-circuit, return True
elif item[6] != "H": # This will never get seen (on this particular dataset)
return True
return False
print "Wrong (Expanded): ", filter(len57notHWrongExpanded, list1)
正确的表达式如下:
def len57notH(item):
return len(item) == 5 or (len(item) == 7 and item[6] != "H")
print "Correct : ", filter(len57notH, list1)
展开:
def len57notHExpanded(item):
if len(item) == 5:
return True
elif len(item) == 7:
if item[6] != "H":
return True
return False
print "Correct (Expand): ", filter(len57notHExpanded, list1)
这会使列表理解看起来像:
new_list = [i for i in list1 if (len(i) == 5 or (len(i) == 7 and i[6] != "H"))]
您的代码没有引发IndexError的原因是因为您的所有数据项都是5或7个元素长。这会导致代码在命中i[6] != "H"
表达式之前短路。如果在包含长度不是5或7且长度少于7个元素的数据项的列表上尝试此代码,则会引发IndexError:
list2 = ["CCC-C", "CCC-P", "CCC", "CCC-A-P", "CCC-A-H", "CCC-J", "CCC-S-X"]
new_list = [i for i in list2 if (len(i) == 5 or len(i) == 7 or i[6] != "H")]
Traceback (most recent call last):
File "C:/Users/xxxxxxxx/Desktop/t.py", line 44, in <module>
new_list = [i for i in list2 if (len(i) == 5 or len(i) == 7 or i[6] != "H")]
IndexError: string index out of range
对不起,这是一个很长的答案...