2016-01-27 6 views
0

Я хотел бы использовать bisect (как показано здесь, во втором ответе: Does python have a sorted list?), , но вместо использования списка чисел у меня есть список объектов. В частности, объекты из этого класса: https://networkx.github.io/documentation/latest/_modules/networkx/classes/graph.htmlПереопределение атрибута сортировки в классе, python

Я бы хотел, чтобы список сохранял графики, отсортированные по их количеству узлов. Если я вставляю эти графики в список, это похоже на то, что он вставляется произвольным образом (если я запускаю его много раз, он изменяется между прогонами).

Есть ли функция сортировки, которую каждый класс может определить, что при применении сортировки будет использоваться (например, переопределение оператора на других языках)?

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() 

Если есть другой способ сделать это, было бы здорово.

Благодаря

+0

Нечто подобное может быть в порядке: L_sort = отсортирован (L, ключ = L .__ len__) – matlabit

+0

Понял: L_sort = отсортированный (L, ключ = лямбда-график: graph.number_of_nodes()) – matlabit

+1

Или более просто 'L_sort = sorted (L, key = Graph.number_of_nodes) '. Но это эквивалентно 'L_sort = sorted (L, key = len)' given 'Graph' реализует' __len__'. Вам нужно ссылаться на метод класса, а не на экземпляр, поэтому в вашем первом комментарии «Graph .__ len__» также работал бы. – AChampion

ответ

1

Несколько произвольный порядок вашего списка из-за того, что объекты упорядочены по id (который является производным от адреса памяти объекта в CPython), если они не обеспечивают какой-то другой способ определить упорядоченность.

Простой способ решить вашу проблему - просто использовать встроенный метод list.sort (или функцию sorted), передавая key=len в качестве аргумента функции ключа.

Однако, если вы хотите использовать bisect, чтобы сохранить отсортированный список, вы также можете это сделать, но ваш класс должен определить Rich Comparison methods.

может добавить эти методы в класс графа, но может быть проще (и более чистым) определить новый класс в качестве обертки.

Вот простой пример, который обертывает встроенный тип list. Он определяет частный метод, _cmp для выполнения сравнений по длине, а методы «магического» «Богатого сравнения» - _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, если они определены.