打印按键排序的字典项

时间:2014-12-26 23:47:33

标签: python sorting python-3.x dictionary

class Company(object):
    def __init__(self, name):
        self.name = name
        self.employees = {}

    def addEmployee(self, id, name):
        self.employees[id] = name

    def displayEmployees(self):
        tmp = [ (k,v) for k,v in self.employees.items() ]
        tmp.sort()
        for k,v in tmp:
            print(k, '\t', v)

a = Company('The Company')
a.addEmployee(111, 'Employee1')
a.addEmployee(222, 'Employee2')
a.addEmployee(333, 'Employee3')
a.displayEmployees()

是否有另一种方法可以通过键对字典进行排序,以便在不使用新变量的情况下保持以下输出?:

111      Employee1  
222      Employee2  
333      Employee3

4 个答案:

答案 0 :(得分:4)

对于大量员工而言,接近最优的可能是:

class Company(object):
    def __init__(self, name):
        self.name = name
        self.employee_ids = []
        self.employees = {}
        self.sorted = True

    def addEmployee(self, id, name):
        self.employee_ids.append(id)
        self.employees[id] = name
        self.sorted = False

    def displayEmployees(self):
        if not self.sorted:
            self.employee_ids.sort()
            self.sorted = True
        for k in self.employee_ids:
            print k, '\t', self.employees[k]

这需要O(N)来插入N个员工 - 同时保持每个插入排序的self.employee_ids会进行此类操作O(N squared)。作为交换,这种方法使displayEmployees 最坏情况 O(N log N) - 但往往更好,因为" timsort",Python&#39的超自然优秀表现在现实世界中的排序算法(自然合并的一种变体)。例如,如果您只添加一名员工(可能需要在中间使用随机ID),请拨打displayEmployees,这只是O(N) - timsort magic。

"有效Java" Josh Bloch成名,然后是一名谷歌员工,参加了一场技术讲座,讲述了Python的故事,并且比喻说:-),在通往大马士革的路上被闪电击中 - 拿出他的笔记本电脑(我记得我们都坐着在前排)并开始黑客攻击。不久之后,timsort成为 Java 对一系列对象进行排序的方式(唉,不是一系列基元 - 出于技术原因,必须保持一个不太健壮的变体" quicksort& #34;。)

BTW,timsort以其发明者蒂姆·彼得斯(Tim Peters)命名,蒂姆·彼得斯(Tim Peters)也被称为" timbot"在Python圈子中(在#64;一个机器人"在Python社区中涉及能够快速响应很多技术问题,而且通常是正确的; Tim是第一个如此荣幸的人)。第二个是F.Lundh," effbot"。我后来很荣幸能够被命名为第三名(据我所知,最后一名),作为" martellibot"。但是,我从来没有开发出像timsort一样酷的十分之一算法! - )

TL; DR:使用bisect按排序顺序维护列表是一个经典且显然很酷的想法,但是,不要这样做。我不记得曾经看到一个明显胜利的情况。通常,最好只将append新内容添加到列表中,并根据需要进行排序;偶尔,标准库中的模块heapq(插入为O(log N),而不是O(N)中的bisect)可能更适合特殊应用。

还有一点需要注意:self.sorted标记只是一个微小的(?)优化,如果您可能反复拨打displayEmployees且中间没有addEmployee来电;你可以通过省略它来简化代码,如果这样的模式不会发生,也不会产生任何不良影响 - 无论如何都不会改变大O行为: - )

答案 1 :(得分:2)

仅对键进行排序,并使用sorted()函数查找值:

def displayEmployees(self):
    for key in sorted(self.employees):
        print(key, self.employees[key], sep='\t')

或内联排序项目:

def displayEmployees(self):
    for key, value in sorted(self.employees.items()):
        print(key, value, sep='\t')

答案 2 :(得分:0)

常规决定不记得订单。如果保留您的dict命令对于您的其余代码非常重要,则可以使用Python OrderedDict模块中的collections。您可以在添加员工时执行此操作:

from collections import OrderedDict

# ...

def addEmployee(self, id, name):
    self.employees[id] = name
    self.employees = OrderedDict(sorted(self.employees.items()))

这将始终保持您的self.employees字典顺序,并将您的显示代码缩减为:

def displayEmployees(self):
    for k,v in self.employees.items():
        print(k, '\t', v)

答案 3 :(得分:0)

前几天我用__str__方法创建了一个dict类,它可以按照你想要的方式显示项目。看看你是否对此感兴趣:

class EmployeeDict(dict):
    '''Just a dictionary, but with a better display of data.

    '''

    def __str__(self):
        str_output = ""
        maxlen = len(str(max(self.keys())))
        for key in sorted(self.keys()):
            str_output += "{} | {}\n".format(str(key).rjust(maxlen), self[key])
        return str_output


class Company(object):
    def __init__(self, name):
        self.name = name
        self.employees = EmployeeDict()

    def addEmployee(self, id, name):
        self.employees[id] = name

    def displayEmployees(self):
        print(str(self.employees))

a = Company('The Company')
a.addEmployee(111, 'Employee1')
a.addEmployee(222, 'Employee2')
a.addEmployee(333, 'Employee3')
a.displayEmployees()

输出:

111 | Employee1
222 | Employee2
333 | Employee3