Эквивалент JavaS TreeSet в Python? - PullRequest
18 голосов
/ 26 апреля 2010

Недавно я наткнулся на некоторый Java-код, который просто помещал некоторые строки в Java TreeSet, реализовал для него компаратор на основе расстояний, а затем отправился в веселый путь к закату, чтобы вычислить заданный балл для решения данной проблемы.

Мои вопросы,

  • Существует ли эквивалентная структура данных для Python?

    • Java treeset в основном выглядит как упорядоченный словарь, который может использовать какой-то компаратор для достижения этого упорядочения.
  • Я вижу, что есть PEP для Py3K для OrderedDict, но я использую 2.6.x. Существует множество упорядоченных реализаций dict, кого конкретно можно порекомендовать?

PS, просто добавлю - я мог бы , вероятно, импортировать DictMixin или UserDict и реализовать свой собственный отсортированный / упорядоченный словарь, и сделать это с помощью функции компаратора - но это кажется излишним.

Спасибо.


Обновление. Спасибо за ответы. Чтобы уточнить немного, скажем, у меня есть функция сравнения, которая определена как, (учитывая конкретное значение ln),

def mycmp(x1, y1, ln):
  a = abs(x1-ln)
  b = abs(y1-ln)
  if a<b:
    return -1
  elif a>b:
    return 1
  else:
    return 0

Я немного не уверен, как бы интегрировать это в порядок, указанный в упорядоченной ссылке dict , приведенной здесь .. .

Нечто подобное,

OrderedDict(sorted(d.items(), cmp=mycmp(len)))

Идеи приветствуются.

Ответы [ 5 ]

5 голосов
/ 26 апреля 2010

Документы Python 2.7 для collections.OrderedDict имеют ссылку на рецепт OrderedDict , который работает на Python 2.4 или выше.

Редактировать: В отношении сортировки: используйте key= вместо cmp=.Это приводит к более быстрому коду , кроме того, в Python3 исключено ключевое слово cmp=.

d={5:6,7:8,100:101,1:2,3:4}
print(d.items())
# [(1, 2), (3, 4), (100, 101), (5, 6), (7, 8)]

Код, который вы разместили для mycmp, не дает ясностито, что вы хотите, передается как x1.Ниже я предполагаю, что x1 должен быть значением в каждой паре ключ-значение.Если это так, вы можете сделать что-то вроде этого:

length=4
print(sorted(d.items(),key=lambda item: abs(item[1]-length) ))
# [(3, 4), (1, 2), (5, 6), (7, 8), (100, 101)]

key=... передается функция, lambda item: abs(item[1]-length).Для каждого item в d.items() лямбда-функция возвращает число abs(item[1]-length).Этот номер действует как прокси для элемента в том, что касается сортировки.См. это эссе для получения дополнительной информации о сортировке идиом в Python.

PS.len - встроенная функция Python.Чтобы len не забить, я изменил имя переменной на length.

3 голосов
/ 19 марта 2016

Недавно я реализовал TreeSet для Python, используя модуль bisect.

https://github.com/fukatani/TreeSet

Его использование аналогично Treeset в Java.

ех.

from treeset import TreeSet
ts = TreeSet([3,7,2,7,1,3])
print(ts)
>>> [1, 2, 3, 7]

ts.add(4)
print(ts)
>>> [1, 2, 3, 4, 7]

ts.remove(7)
print(ts)
>>> [1, 2, 3, 4]

print(ts[2])
>>> 3
2 голосов
/ 26 апреля 2010

Мне нужно посмотреть некоторые примеры данных, но если вы просто пытаетесь выполнить взвешенную сортировку, то встроенный python sorted () может сделать это двумя способами.

С хорошо упорядоченными кортежами и функцией key ():

def cost_per_page(book):
    title, pagecount, cost = book
    return float(cost)/pagecount

booklist = [
        ("Grey's Anatomy", 3000, 200),
        ('The Hobbit', 300, 7.25),
        ('Moby Dick', 4000, 4.75),
]
for book in sorted(booklist, key=cost_per_page):
    print book

или с классом с оператором __cmp__.

class Book(object):
    def __init__(self, title, pagecount, cost):
        self.title = title
        self.pagecount = pagecount
        self.cost = cost
    def pagecost(self):
        return float(self.cost)/self.pagecount
    def __cmp__(self, other):
        'only comparable with other books'
        return cmp(self.pagecost(), other.pagecost())
    def __str__(self):
        return str((self.title, self.pagecount, self.cost))

booklist = [
        Book("Grey's Anatomy", 3000, 200),
        Book('The Hobbit', 300, 7.25),
        Book('Moby Dick', 4000, 4.75),
]
for book in sorted(booklist):
    print book

Оба они возвращают один и тот же вывод:

('Moby Dick', 4000, 4.75)
('The Hobbit', 300, 7.25)
("Grey's Anatomy", 3000, 200)
0 голосов
/ 26 апреля 2010

Если вам нужен набор, который всегда повторяется в отсортированном порядке, это может помочь вам в этом:

def invalidate_sorted(f):
    def wrapper(self, *args, **kwargs):
        self._sort_cache = None
        return f(self, *args, **kwargs)
    return wrapper

class SortedSet(set):
    _sort_cache = None

    _invalidate_sort_methods = """
        add clear difference_update discard intersection_update
        symmetric_difference_update pop remove update
        __iand__ __ior__ __isub__ __ixor__
        """.split()

    def __iter__(self):
        if not self._sort_cache:
            self._sort_cache = sorted(set.__iter__(self))
        for item in self._sort_cache:
            yield item

    def __repr__(self):
        return '%s(%r)' % (type(self).__name__, list(self))

    for methodname in _invalidate_sort_methods:
        locals()[methodname] = invalidate_sorted(getattr(set, methodname))
0 голосов
/ 26 апреля 2010

1. Я не думаю, что в Python есть встроенные сортированные наборы. Как насчет этого?

letters = ['w', 'Z', 'Q', 'B', 'C', 'A']
  for l in sorted(set(letters)):
     print l

2.Java TreeSet является реализацией абстракции под названием SortedSet. Базовые типы будут отсортированы в естественном порядке. Экземпляр TreeSet выполняет все сравнения ключей, используя свой метод CompareTo (или сравнение). Поэтому ваши пользовательские ключи должны реализовывать правильные compareTo

...