开发者

Rm duplication in list comprehension

Input is a string, the idea is to count the letters A-z only, and print them alphabeticall开发者_如何转开发y with the count of appearances.

As usual I kept at this 'till I got a working result, but now seek to optimize it in order to better understand the Python way of doing things.

def string_lower_as_list(string):
    """
      >>> string_lower_as_list('a bC')
      ['a', ' ', 'b', 'c']
    """
    return list(string.lower())

from sys import argv

letters = [letter for letter in string_lower_as_list(argv[1]) 
            if ord(letter) < 124 and ord(letter) > 96]

uniques = sorted(set(letters))

for let in uniques:
    print let, letters.count(let)
  1. How do I remove the duplication of ord(letter) in the list comprehension?
  2. Would there have been any benefit in using a Dictionary or Tuple in this instance, if so, how?

EDIT Should have said, Python 2.7 on win32


You can compare letters directly and you actually only need to compare lower case letters

letters = [letter for letter in string_lower_as_list(argv[1]) 
            if "a" <= letter <= "z"]

But better would be to use a dictionary to count the values. letters.count has to traverse the list every time you call it. But you are already traversing the list to filter out the right characters, so why not count them at the same time?

letters = {}

for letter in string_lower_as_list(argv[1]):
    if "a" <= letter <= "z":
        letters[letter] = letters.get(letter, 0) + 1

for letter in sorted(letters):
    print letter, letters[letter] 

Edit: As the others said, you don't have to convert the string to a list. You can iterate over it directly: for letter in argv[1].lower().


How do I remove the duplication of ord(letter) in the list comprehension?

You can use a very Python-specific and somewhat magical idiom that doesn't work in other languages: if 96 < ord(letter) < 124.

Would there have been any benefit in using a Dictionary or Tuple in this instance, if so, how?

You could try using the collections.Counter class added in Python 2.7.

P.S. You don't need to convert the string to a list in order to iterate over it in the list comprehension. Any iterable will work, and strings are iterable.

P.S. 2. To get the property 'this letter is alphabetic', instead of lowercasing and comparing to a range, just use str.isalpha. Unicode objects provide the same method, which allows the same code to Just Work with text in foreign languages, without having to know which characters are "letters". :)


You don't have to convert string to list, string is iterable:

letters = {}
for letter in argv[1].lower():
    if "a" <= letter <= "z":
        letters[letter] = letters.get(letter, 0) + 1

for letter in sorted(letters.keys()):
    print letter, letters[letter]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜