Python拼图代码评论(剧透)

sc_*_*ray 4 python algorithm

我一直在研究Python Challenge中提出的问题.其中一个问题是要筛选出一堆乱七八糟的角色并挑出最稀有的角色.

我的方法是从文本文件中读取字符,将字符/出现作为键/值对存储在字典中.按值对字典进行排序,并将出现为键的字典反转,字符串为值.假设最稀有的字符只出现一次,我返回这个反向字典的键等于1的值.

输入(funkymess.txt)是这样的:

%% $ @ $ ^ _#)^)&!_ +]!*@&^} @@ %% + $&[(_ @%+%$*^ @ $ ^!+]!&#)*} {}}!} ] $ [%} @ [{ @#_ ^ {*......

代码如下:

from operator import itemgetter
characterDict = dict()

#put the characters in a dictionary
def putEncounteredCharactersInDictionary(lineStr):
    for character in lineStr:
        if character in characterDict:
            characterDict[character] = characterDict[character]+1
        else:
            characterDict[character] = 1

#Sort the character dictionary
def sortCharacterDictionary(characterDict):
    sortCharDict = dict()
    sortsortedDictionaryItems = sorted(characterDict.iteritems(),key = itemgetter(1))
    for key, value in sortsortedDictionaryItems:
        sortCharDict[key] = value
    return sortCharDict 

#invert the sorted character dictionary
def inverseSortedCharacterDictionary(sortedCharDict):
    inv_map = dict()
    for k, v in sortedCharDict.iteritems():
        inv_map[v] = inv_map.get(v, [])
        inv_map[v].append(k)
    return inv_map


f = open('/Users/Developer/funkymess.txt','r')
for line in f:
    #print line
    processline = line.rstrip('\n')
    putEncounteredCharactersInDictionary(processline)
f.close()

sortedCharachterDictionary = sortCharacterDictionary(characterDict)
#print sortedCharachterDictionary
inversedSortedCharacterDictionary = inverseSortedCharacterDictionary(sortedCharachterDictionary)
print inversedSortedCharacterDictionary[1]r
Run Code Online (Sandbox Code Playgroud)

有人可以看看并向我提供一些关于我是否在这里的正确轨道的指示,并且如果可能的话,从语言和算法的角度提供关于可能的优化/最佳实践和潜在重构的一些反馈.

谢谢

Joh*_*ica 7

重构:演练

我想引导您完成重构过程.学习编程不仅仅是了解最终结果,这是您在Stack Overflow上提出问题时通常会得到的结果.这是关于如何自己获得答案的.当人们发布这样一个问题的简短而密集的答案时,他们如何得出他们的解决方案并不总是很明显.

那么让我们做一些重构,看看我们可以做些什么来简化你的代码.我们将重写,删除,重命名和重新排列代码,直到无法进行更多改进.

简化您的算法

Python不需要那么冗长.当您在Python中使用列表和dicts操作显式循环时,通常会出现代码异味,而不是使用对容器作为整体进行操作的列表推导和函数.

使用defaultdict存储字符计数

defaultdict(int)如果它们不存在,A 将在访问它们时生成条目.这让我们在计算字符时消除if/else分支.

from collections import defaultdict
characterDict = defaultdict(int)

def putEncounteredCharactersInDictionary(lineStr):
    for character in lineStr:
        characterDict[character] += 1
Run Code Online (Sandbox Code Playgroud)

排序dicts

字典不保证其密钥的任何排序.您不能假设这些项目的存储顺序与您插入它们的顺序相同.因此,对dict条目进行排序,然后将它们放回到另一个dict中,只需将它们重新加入即可.

这意味着你的功能基本上是一个无操作.对项目进行排序后,您需要将它们保留为元组列表以保留其排序顺序.删除该代码后,我们可以将此方法减少到一行.

def sortCharacterDictionary(characterDict):
    return sorted(characterDict.iteritems(), key=itemgetter(1))
Run Code Online (Sandbox Code Playgroud)

反转词

鉴于之前的评论,您在排序后将不再拥有dict.但假设您这样做,此函数是不鼓励显式循环的情况之一.在Python中,始终考虑如何一次操作集合而不是一次操作一个项目.

def inverseSortedCharacterDictionary(sortedCharDict):
    return dict((v, k) for k, v in sortedCharDict.iteritems())
Run Code Online (Sandbox Code Playgroud)

在一行中,我们(1)迭代dict中的键/值对; (2)切换它们并创建反转值/键元组; (3)用这些倒置的元组创建一个字典.

明智地评论和命名

您的方法名称很长且具有描述性.没有必要在评论中重复相同的信息.只有当你的代码是不是自我描述,例如,当你有一个复杂的算法或不同寻常的结构不是很直观,因为使用的意见.

在命名方面,你的名字不必要很长.我要坚持远小于描述性的名字,也使他们更通用.而不是inverseSortedCharacterDictionary,试试吧invertedDict.这就是所有方法所做的,它颠倒了一个字典.它,如果它通过一个排序字符字典或任何其他类型的字典中实际上并不重要.

作为一个经验法则,尝试使用可能是最通用的名称,以便您的方法和变量可以尽可能通用.更通用意味着更可重用.

characters = defaultdict(int)

def countCharacters(string):
    for ch in string:
        characters[ch] += 1

def sortedCharacters(characters):
    return sorted(characters.iteritems(), key=itemgetter(1))

def invertedDict(d):
    return dict((v, k) for k, v in d.iteritems())
Run Code Online (Sandbox Code Playgroud)

减少音量

使用临时变量和辅助方法是一种很好的编程习惯,我赞赏你在程序中这样做.但是,既然我们已经足够简单,每个只有一两行,我们可能甚至不再需要它们了.

这是改变上述功能后的程序体:

f = open('funkymess.txt', 'r')

for line in f:
    countCharacters(line.rstrip('\n'))

f.close()

print sortedCharacters(characters)[0]
Run Code Online (Sandbox Code Playgroud)

然后让我们继续介绍那些辅助方法,因为它们非常简单.这是所有重构后的最终程序:

最后的节目

#!/usr/bin/env python

from operator import itemgetter
from collections import defaultdict

characters = defaultdict(int)

f = open('funkymess.txt','r')

for line in f:
    for ch in line.rstrip('\n'):
        characters[ch] += 1

f.close()

print sorted(characters.iteritems(), key=itemgetter(1))[0]
Run Code Online (Sandbox Code Playgroud)