仅在名称长于之前的名称时打印名称

时间:2011-05-24 07:29:03

标签: python

假设你有一个名单[“sam”,“janet”,“bob”,“samantha”]。 你会如何用Python编写一个程序,只有当它比它之前的那个更长时才打印它。

5 个答案:

答案 0 :(得分:5)

使用来自itertoolspairwise食谱以及列表理解让我感觉最为抒情:

>>> from itertools import izip, tee
>>> def pairwise(iterable):
...     "s -> (s0,s1), (s1,s2), (s2, s3), ..."
...     a, b = tee(iterable)
...     next(b, None)
...     return izip(a, b)
...
>>> namelist = ["sam", "janet", "bob","samantha"]
>>> [b for a,b in pairwise(namelist) if len(b) > len(a)]
['janet', 'samantha']

更新

从您的问题中不清楚list中的名字是否应该被计算为比之前的 none 更长或更短。上述解决方案排除了它。如果您(或您的老师?)想要包括第一项:

>>> [namelist[0]] + [b for a,b in pairwise(namelist) if len(b) > len(a)]
['sam', 'janet', 'samantha']

答案 1 :(得分:2)

a = ["sam", "janet", "bob", "samantha"]

# two similar one-liners:
print ', '.join(a2 for a1, a2 in zip(a[:-1],a[1:]) if len(a2) > len(a1))
print ', '.join(a[i] for i in xrange(1, len(a)) if len(a[i]) > len(a[i-1]))

# output of both of them:
janet, samantha

答案 2 :(得分:2)

到目前为止只有5个答案。 他们都没有打印名字。当然,很多人可以很容易地改变这样做,但只是为了它,这是一个。我会很好地分解它。

python itertools模块是自11个脚极以来最伟大的事情,并且这个问题的一个特别有希望的迭代器是ifilter,它在列表中的每个项目上调用给定函数,并仅输出函数返回True的那些函数。所以我们想做这样的事情:

from itertools import ifilter

names = ["sam", "janet", "bob", "jane", "samantha"]
for name in ifilter(longer_than_previous, names):
    print name   # Output: sam (?), janet, jane, samantha

所以我们尚未定义的函数longer_than_previous将首先调用“sam”作为参数,然后是“janet”,“bob”等等。现在的问题是函数通常没有内存,所以我们需要某种技巧来使函数记住最后一个参数的长度并将其与当前参数的长度进行比较。

这种天真的做法是全球性的争论。假设在上面给出的代码之前粘贴了以下代码:

last_name_length = 0

def longer_than_previous(name):
    global last_name_length
    is_longer = len(name) > last_name_length
    last_name_length = len(name)
    return is_longer

现在,使用全局变量来存储实际只需要一个地方的值被认为是不好的做法。是否有另一种方式来提供我们的功能记忆?好吧,在python中,一切都是一个对象,所以我们可以给函数本身一个属性(警告,前面丑陋的代码):

def longer_than_previous(name):
    if not hasattr(longer_than_previous, "last_name_length"):
        longer_than_previous.last_name_length = 0
    is_longer = len(name) > longer_than_previous.last_name_length
    longer_than_previous.last_name_length = len(name)
    return is_longer

好吧,这并没有完全提高可读性,我们必须使用hasattr,我发现这是一个很好的迹象,我设计的东西很糟糕。此外,此功能仅可用一次,之后我们必须使用longer_than_previous.last_name_length = 0手动重置它。所以我们希望能够创建这样的几个一次性函数,每个函数都有一个属性来存储最后一个长度。嗯,这对于一个类来说听起来不错。毕竟,类是在调用时生成具有属性的对象的东西。但是对象需要像一个函数一样行事。我们可以使用__call__特殊方法实现这一点,如下所示:

class LongerThanPrevious(object):
    def __init__(self):
        self.last_name_length = 0

    def __call__(self, name):
        is_longer = len(name) > self.last_name_length
        self.last_name_length = len(name)
        return is_longer

现在我们只需要更改顶部的代码,以便它使用LongerThanPrevious类的对象而不是函数long_than_previous:

for name in ifilter(LongerThanPrevious(), names):
    print name   # Output: sam (?), janet, jane, samantha

现在情况好多了,而且非常易读。我在山姆之后放了一个问号,因为这个问题是否应该被包括在内。改变课程很容易,因此不包括在内:

    def __init__(self):
        self.last_name_length = float("infinity")

注意:答案已完全重写。

答案 3 :(得分:1)

直接的:

oldlen=0
for f in ["vusi", "angelina", "uma", "johnny", "sizwe", "kate", "charlize", "meryl"]:
    x=len(f) 
    if x>oldlen:
        print(f)
    oldlen=x

我们的想法是将先前的打印长度存储在变量中。

答案 4 :(得分:1)

我会试试这个:

names = ["sam", "janet", "bob","samantha"]
last_name = None
for name in names:
    if last_name and len(name) > len(last_name):
        print name
    last_name = name

或(以更加pythonic的方式):

names = ["sam", "janet", "bob","samantha"]
print '\n'.join(name for i, name in enumerate(names) if i>0 and len(name) > len(names[i-1]))

当然,不会打印出第一个名字。