更复杂的排序:如何在类别中排序?

时间:2015-07-13 01:38:49

标签: python python-2.7 sorting

我对我正在尝试修改的当前程序有疑问。我目前的计划:

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函数的情况下实现这一点。

1 个答案:

答案 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))