覆盖类python中的排序属性

时间:2016-01-27 08:49:41

标签: python list sorting bisect

我想使用bisect(如此处所示,在第二个答案中:Does python have a sorted list?), 但我没有使用数字列表,而是有一个对象列表。具体而言,此类中的对象:https://networkx.github.io/documentation/latest/_modules/networkx/classes/graph.html

我希望列表能够按照节点数量对图表进行排序。 如果我将这些图形推入列表中,看起来它是以任意方式插入的(如果我多次运行它,它会在运行之间发生变化)。

有"排序"每个类可以定义的函数,在应用排序时,它将被使用(就像在其他语言中重写操作符一样)?

import bisect
import networkx as nx

L=[]
G1 = nx.Graph()
G2 = nx.Graph()

G1.add_edges_from([(1,2),(1,3),(2,3),(3,4),(4,5),(4,6),(5,6),(4,7),(7,8),(7,9),(8,9)])
print 'G1', G1.number_of_nodes()
G2.add_edges_from([(1,2),(1,3)])
print 'G2', G2.number_of_nodes()

bisect.insort(L,G1)
bisect.insort(L,G2)

print 'L0 ', L[0].number_of_nodes()
print 'L1' ,L[1].number_of_nodes()

如果有另一种方法,那就太棒了。

由于

1 个答案:

答案 0 :(得分:1)

列表的某些任意顺序是由于对象按id排序(它是从CPython中对象的RAM地址派生的),除非它们提供了一些定义排序的其他方法。

解决问题的简单方法是简单地使用内置的list.sort方法(或sorted函数),将key=len作为关键函数参数传递。

但是,如果您想使用bisect维护已排序的列表,也可以这样做,但您的类需要定义Rich Comparison methods

可以将这些方法添加到图表类中,但将新类定义为包装器可能更容易(也更清晰)。

这是一个包含内置list类型的简单示例。它定义了一个私有方法_cmp来执行基于长度的比较,而Rich Comparison“magic”方法调用_cmp。为了提高效率,应该直接定义Rich Comparison方法 ,以避免调用另一个方法,但使用_cmp更容易阅读(和写:) :)。

import bisect

class MyList(object):
    def __init__(self, data):
        self.data = data

    def __repr__(self):
        return 'MyList({0!r})'.format(self.data)

    def _cmp(self, other):
        return len(self.data) - len(other.data)

    #Rich comparison methods
    def __lt__(self, other):
        return self._cmp(other) < 0

    def __le__(self, other):
        return self._cmp(other) <= 0

    def __eq__(self, other):
        return self._cmp(other) == 0

    def __ne__(self, other):
        return self._cmp(other) != 0

    def __ge__(self, other):
        return self._cmp(other) >= 0

    def __gt__(self, other):
        return self._cmp(other) > 0


data = (
    [50, 60],
    [10, 20, 30],
    [1, 2, 3, 4, 5],
    [5, 6],
    [7, 8, 9, 10],
)

blist = []
for seq in data:
    a = MyList(seq)
    bisect.insort(blist, a)
    print(a)
    print(blist)
    print()    

<强>输出

MyList([50, 60])
[MyList([50, 60])]

MyList([10, 20, 30])
[MyList([50, 60]), MyList([10, 20, 30])]

MyList([1, 2, 3, 4, 5])
[MyList([50, 60]), MyList([10, 20, 30]), MyList([1, 2, 3, 4, 5])]

MyList([5, 6])
[MyList([50, 60]), MyList([5, 6]), MyList([10, 20, 30]), MyList([1, 2, 3, 4, 5])]

MyList([7, 8, 9, 10])
[MyList([50, 60]), MyList([5, 6]), MyList([10, 20, 30]), MyList([7, 8, 9, 10]), MyList([1, 2, 3, 4, 5])]

您可能希望看一下heapq:您可能会发现它比bisect更适合您的目的。 heapq(当然)将使用Rich Comparison方法(如果已定义)。