2010-11-02 79 views
5

我应该采取单词列表并计算其中的所有单词,它是2个或更多字符长,第一个和最后一个字符相等。列表理解和len()与简单for循环

我想出了两种可能的解决方案:

result = 0 
for word in words: 
    if len(word) >= 2 and word[0] == word[-1]: 
     result += 1 
return result 

return len([word for word in words if len(word) >= 2 and word[0] == word[-1]]) 

哪一个将是首选的解决方案?或者还有更好的吗?

+0

我会采取#2:但格式很好,在多行。仅仅因为你*可以*写它一行并不意味着你应该(即使有发电机或补偿等) – 2010-11-03 00:08:04

+0

请请,请测量。请使用'timeit'来衡量。请测量并发布结果。 – 2010-11-03 01:17:07

+1

@ S.洛特:他对演出一无所知。 *首选*做某事的方式并不意味着最快的做法。 – 2010-11-03 09:05:04

回答

14

在第二个例子中,如果列表很大,那么generator expression会比list-comp更好。

sum(1 for word in words if len(word) >= 2 and word[0] == word[-1]) 
+1

TypeError:'generator'类型的对象没有len() – dan04 2010-11-02 23:51:17

+0

谢谢!我几乎会建议它。 – pyfunc 2010-11-02 23:51:37

+0

@ dan04:谢谢;现在修好。 @pyfunc:谢谢! – bernie 2010-11-02 23:55:21

1

两者都很不错。

有小的差异:

列表理解返回其要传递到LEN另一个列表。第一种解决方案避免了创建另一个列表。

3

第一个肯定是Python中的首选解决方案。

不要忘记你的禅的Python:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.

Explicit is better than implicit.

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

Sparse is better than dense.

Readability counts.

Special cases aren't special enough to break the rules.

Although practicality beats purity.

Errors should never pass silently.

Unless explicitly silenced.

In the face of ambiguity, refuse the temptation to guess.

There should be one-- and preferably only one --obvious way to do it.

Although that way may not be obvious at first unless you're Dutch.

Now is better than never.

Although never is often better than right now.

If the implementation is hard to explain, it's a bad idea.

If the implementation is easy to explain, it may be a good idea.

Namespaces are one honking great idea -- let's do more of those!

除此之外,您的解决方案是好的。

+4

通常的Python-parroting的公式:提出一个声明,并将其作为理由指向一条线,就好像它是一些宗教文本。 (我发现第二个版本非常清晰;第一个看起来像从C移植过来的东西)。 – 2010-11-03 00:03:28

+0

我完全不同意。列表理解*非常* Pythonic和可读。 – 2010-11-03 03:12:07

2

我个人发现这个显式循环更具可读性,但它有很大的味道(有些人更喜欢较短的代码,特别是当他们必须编写代码时)。

任一版本可以进一步缩短的/改进:

result = 0 
for word in words: 
    result += int(len(word) >= 2 and word[0] == word[-1]) 
return result 

的int()转换严格地说不必要的,因为真正的是一种如图1所示,但它可以是用于可读性更好。同样的方法也适用于理解:

return sum(len(word) >= 2 and word[0] == word[-1] for word in words) 

如果你想使用LEN(),我想读者指出,事实上,这些值并不真正的问题:

len(1 for word in words if len(word) >= 2 and word[0] == word[-1]) 
+0

'a + = int(bool)'是单一的,我称它为邪恶。不要那样做;原来的情况更加清晰。 – 2010-11-03 00:14:55

1

您可能要考虑的其他一些变体:

首先,您可以将过滤条件分解为函数。这状况良好无论哪种方式,但如果它变得更多复杂的,我肯定会做到这一点:

def check(word): 
    return len(word) >= 2 and word[0] == word[-1] 
sum(1 for word in words if check(word)) 

接下来,如果生成列表(如在原始列表理解)是可以接受的,那么你可以这样做:

len(filter(check, words)) 

有itertools.ifilter,但如果你使用,你需要再次使用sum表达,所以它不会落得更清楚。

sum这个技巧经常出现,我很惊讶没有标准的库调用来计算迭代器中的项数(如果有的话,我没有找到它)。或者,如果len会消耗并计算迭代器中的条目数(如果它没有__len__),但它不会。