如果没有值,则为最大值 - python

时间:2015-05-04 14:47:57

标签: python python-2.7 list-comprehension

如果满足某些条件,我想在列表中返回一个项目。一个条件是我的项目是"Project A",但另一个条件是t[1]对于包含None的所有子列表都不是"Project A"。我的代码有效,但似乎效率低下。我怎样才能把它结合起来?

mylist = [(1, None, "Project A"), (2, 3, "Project A"), (3, 6, "Project B")]

try:
    if None not in [t[1] for t in mylist if t[2] == "Project A"]:
        print max(t for t in mylist if t[2] == "Project A" and t[1] is not None)
    else:
        print "no match"
except ValueError:
    print "no match"

4 个答案:

答案 0 :(得分:1)

由于您无论如何都需要验证所有匹配的条目,因此最佳选择是使用直接for循环;在未达到None条件时爆发:

found = None
for entry in mylist:
    if entry[2] == 'Project A':
        if entry[1] is None:
            print 'No match'
            break
        if not found or entry > found:
            found = entry
else:
    # only executed when there was no break!
    print found or 'No match'

else循环的for分支仅在for循环完成迭代时执行。只有在Project A被设置为t[1]的情况下找到None个条目时才会发生这种情况。

由于仍有可能存在与项目名称匹配的0个条目,因此found首先设置为None;如果没有匹配的条目,那么当您到达None阻止循环时,它仍为else

演示,将找到的None 案例转换为例外以显示差异:

>>> def find_max_project(projects, target):
...     found = None
...     for entry in projects:
...         if entry[2] == target:
...             if entry[1] is None:
...                 raise ValueError('no match')
...             if not found or entry > found:
...                 found = entry
...     else:
...         return found
... 

>>> find_max_project([(1, None, "Project A"), (2, 3, "Project A"), (3, 6, "Project B")], 'Project A')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in find_max_project
ValueError: 'no match'
>>> find_max_project([(1, 4, "Project A"), (2, 3, "Project A"), (3, 6, "Project B")], 'Project A')
(2, 3, 'Project A')
>>> find_max_project([(1, 2, "Project A"), (1, 3, "Project A")], 'Project A')
(1, 3, 'Project A')
>>> find_max_project([(1, 2, "Project B"), (1, 3, "Project B")], 'Project A')
>>> find_max_project([(1, 2, "Project B"), (1, 3, "Project B")], 'Project A') is None
True

请注意,在这个版本中,我们甚至不需要将最后一行放在else块中,因为使用异常现在会结束该函数。

答案 1 :(得分:1)

tmp = [x for x in mylist if x[2] == "Project A"]
if tmp and None not in zip(*tmp)[1]:
    print max(tmp)
else:
    print "no match"

答案 2 :(得分:1)

您可以过滤并返回最大值,如果有"Project A"的任何无,您不应该立即返回没有匹配项:

 def filtered(l,proj):
    filt = []
    for t in l:
        if t[2] == proj:
            if t[1] is None:
                return "No match"
            filt.append(t)
    return max(filt)

答案 3 :(得分:0)

我更喜欢Martijn的简单for循环,但仅供讨论,您可以使用key参数将None值设为最大值(如果存在),否则返回最大值条目:

try:
    result = max((t for t in mylist if t[2] == "Project A"),
                 key=lambda x: (x[1] is None, x))
    print 'no match' if result[1] == None else result
except ValueError:
    print 'no match'

如果您确保Project A在列表中,那么您可以摆脱try块。