我对我正在尝试修改的当前程序有疑问。我目前的计划:
def extract_names(filename):
names = []
f = open(filename, 'rU')
text = f.read()
yearmatch = re.search(r'Popularity\sin\s(\d\d\d\d)', text)
if not yearmatch:
sys.stderr.write('unavailable year\n')
sys.exit(1)
year = yearmatch.group(1)
names.append(year)
yeartuples = re.findall(r'<td>(\d+)</td><td>(\w+)</td>\<td>(\w+)</td>', text)#finds all patterns of date, boyname, and girlname, creates tuple)
rankednames = {}
for rank_tuple in yeartuples:
(rank, boyname, girlname) = rank_tuple
if boyname not in rankednames:
rankednames[boyname] = rank
if girlname not in rankednames:
rankednames[girlname] = rank
sorted_names = sorted(rankednames.keys(), key=lambda x: int(rankednames[x]), reverse = True)
for name in sorted_names:
names.append(name + " " + rankednames[name])
return names[:20]
#Boilerplate from this point**
def main():
args = sys.argv[1:]
if not args:
print 'usage: [--summaryfile] file [file ...]'
sys.exit(1)
summary = False
if args[0] == '--summaryfile':
summary = True
del args[0]
for filename in args:
names = extract_names(filename)
text = '\n'.join(names)
if summary:
outf = open(filename + '.summary', 'w')
outf.write(text + '\n')
outf.close()
else:
print text
if __name__ == '__main__':
main()
从网站上获取有关某一年份中最受欢迎的婴儿名字的信息,使用此数据创建一个列表并按照从最低等级(1000)到最高等级的顺序打印出婴儿名称列表等级(1)。我试图进行的修改应该按字母(第一个)排序所有名称,但在每组字母(所有a的组,所有b的组等)中排序。我试图按降序对名称进行排序在字母组中,所以以a开头的排名最低的名称将是显示的第一个名称。我最初能够通过修改lambda函数来执行此操作,以便sorted_names = sorted(rankednames.keys(),key=lambda x: (x[0], int(rankednames[x], reverse = True))
但是,我希望能够在没有修改lambda函数的情况下实现这一点。
答案 0 :(得分:0)
显而易见的解决办法是修改你的lambda函数,以便它返回一个2元组(letter, rank)
。由于您希望按字母顺序排序并按排名递减,因此您需要否定后者(而不是使用reverse=True
):
sorted_names = sorted(rankednames, key=lambda x: (x[0], -int(rankednames[x])))
我能想到的唯一选择是排序两次,首先按排名(反向)然后按第一个字母排序:
sorted_names = sorted(sorted(rankednames,
key=lambda x: int(rankednames[x]),
reverse=True),
key=lambda x: x[0])
这是有效的,因为Python的Timsort是稳定的(它以与输入中相同的顺序保持相等的键值)。这可能比仅排序一次慢一点,尽管在一般情况下它仍然是O(N log(N))
。