如果Python中的条件为真,则从现有列表创建列表

时间:2011-11-30 06:59:31

标签: python list conditional-statements

我正在尝试从列表中删除一些项目,

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”错误。有什么想法吗?

此致

4 个答案:

答案 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

对不起,这是一个很长的答案...