[英]Creating a list from an existing list if a condition is true in Python
我正在嘗試從列表中刪除一些項目,
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-AH”項。 此外,在i [6]中檢查項目“ CCC-C”時,不會出現“ IndexError:字符串索引超出范圍”錯誤。 有任何想法嗎?
問候,
Python中的布爾表達式按以下順序執行:
>>> A() or B()
如果A()返回True,則無需檢查B()
>>> A() and B()
如果A()返回False,則無需檢查B()
我希望它能給您一些想法。
做這個:
new_list = [i for i in list1 if len(i)==5 or (len(i)==7 and i[6]!="H")]
這樣,除非最后一個字符是H
(條件(len(i)==7 and i[6]!="H")
,否則您只會得到長度為5(條件len(i)==5
)或長度為7的項目。 (len(i)==7 and i[6]!="H")
)。
僅當字符串的長度為7時,才會評估可能發生IndexError
條件i[6]!="H"
,以確保您不會遇到此錯誤。
此外,在i [6]中檢查項目“ CCC-C”時,不會出現“ IndexError:字符串索引超出范圍”錯誤。
or
短路。 如果為or或條件指定的第一個條件為True
,則不計算第二個條件,無論第二個參數的真值如何,總評估值仍為True
。
另外,“ CCC-AH”之所以匹配,是因為它的長度是7。如果您不希望那些以H結尾在第7位的字符串,無論它們的長度如何,都應重做邏輯表達式:
new_list = [i for i in list1 if (len(i) == 5 or len(i) == 7) and (i[6] != "H")]
正如其他人指出的那樣, len("CCC-AH") == 7
並且python對布爾運算采用短路評估。 最終結果是:
(len("CCC-A-H") == 5 or len("CCC-A-H") == 7 or "CCC-A-H"[6] != "H")
將返回true,因為len("CCC-AH") == 7
評估"CCC-AH"[6] != "H"
之前len("CCC-AH") == 7
true,因此len("CCC-AH") == 7
"CCC-AH"[6] != "H"
。
通過使用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
抱歉,答案很長...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.