Ответ 1

Существует рецепт упорядоченного набора (возможный новый канал) для этого, который упоминается в документации Python 2. Это выполняется на Py2.6 или более поздней версии и версии 3.0 или более поздней версии без каких-либо изменений. Интерфейс почти точно совпадает с нормальным набором, за исключением того, что инициализация должна выполняться со списком.

OrderedSet([1, 2, 3])

Это MutableSet, поэтому подпись для .union не совпадает с сигнатурой set, но поскольку она включает __or__ можно легко добавить что-то подобное:

@staticmethod
def union(*sets):
    union = OrderedSet()
    union.union(*sets)
    return union

def union(self, *sets):
    for set in sets:
        self |= set

Ответ 2

Упорядоченный набор функционально является частным случаем упорядоченного словаря.

Клавиши словаря уникальны. Таким образом, если игнорировать значения в упорядоченном словаре (например, назначая их None), то по существу есть упорядоченный набор.

Начиная с Python 3.1 collections.OrderedDict, Ниже приведен пример реализации OrderedSet. (Обратите внимание, что нужно определить или переопределить только несколько методов: collections.OrderedDict и collections.MutableSet сделать тяжелый подъем.)

import collections

class OrderedSet(collections.OrderedDict, collections.MutableSet):

    def update(self, *args, **kwargs):
        if kwargs:
            raise TypeError("update() takes no keyword arguments")

        for s in args:
            for e in s:
                 self.add(e)

    def add(self, elem):
        self[elem] = None

    def discard(self, elem):
        self.pop(elem, None)

    def __le__(self, other):
        return all(e in other for e in self)

    def __lt__(self, other):
        return self <= other and self != other

    def __ge__(self, other):
        return all(e in self for e in other)

    def __gt__(self, other):
        return self >= other and self != other

    def __repr__(self):
        return 'OrderedSet([%s])' % (', '.join(map(repr, self.keys())))

    def __str__(self):
        return '{%s}' % (', '.join(map(repr, self.keys())))

    difference = property(lambda self: self.__sub__)
    difference_update = property(lambda self: self.__isub__)
    intersection = property(lambda self: self.__and__)
    intersection_update = property(lambda self: self.__iand__)
    issubset = property(lambda self: self.__le__)
    issuperset = property(lambda self: self.__ge__)
    symmetric_difference = property(lambda self: self.__xor__)
    symmetric_difference_update = property(lambda self: self.__ixor__)
    union = property(lambda self: self.__or__)

Ответ 3

Ответ отрицательный, но вы можете использовать collections.OrderedDict из стандартной библиотеки Python только с ключами (и значениями, как None) для той же цели.

Обновление: Начиная с Python 3.7 (и CPython 3.6), стандарт dict гарантированно сохраняет порядок и более производительный, чем OrderedDict. (Однако для обратной совместимости и особенно читабельности вы можете продолжить использовать OrderedDict.)

Вот пример того, как использовать dict в качестве упорядоченного набора для отфильтровывания дублирующихся элементов при сохранении порядка, тем самым эмулируя упорядоченный набор. Используйте метод класса dict fromkeys(), чтобы создать диктовку, а затем просто попросите вернуть keys().

>>> keywords = ['foo', 'bar', 'bar', 'foo', 'baz', 'foo']

>>> list(dict.fromkeys(keywords).keys())
['foo', 'bar', 'baz']

Ответ 4

Я могу сделать вас лучше, чем OrderedSet: у boltons есть чистый-Python, 2/3-совместимый тип IndexedSet который является не только упорядоченным набором, но также поддерживает индексирование (как со списками).

Просто pip install boltons (или скопируйте setutils.py в свою кодовую базу), импортируйте IndexedSet и:

>>> from boltons.setutils import IndexedSet
>>> x = IndexedSet(list(range(4)) + list(range(8)))
>>> x
IndexedSet([0, 1, 2, 3, 4, 5, 6, 7])
>>> x - set(range(2))
IndexedSet([2, 3, 4, 5, 6, 7])
>>> x[-1]
7
>>> fcr = IndexedSet('freecreditreport.com')
>>> ''.join(fcr[:fcr.index('.')])
'frecditpo'

Все уникально и сохраняется в порядке. Полное раскрытие: я написал IndexedSet, но это также означает, что вы можете IndexedSet ошибку, если есть какие-либо проблемы. :)

Ответ 5

Реализации на PyPI

В то время как другие указали, что в Python нет встроенной реализации набора для сохранения порядка вставки, я чувствую, что в этом вопросе отсутствует ответ, в котором говорится, что можно найти на PyPI.

Насколько мне известно, в настоящее время существует:

Обе версии основаны на рецепте Python по установке объектов для полного списка методов работы с множеством и их эквивалентов на основе операторов.

Сначала я отправился с упорядоченным набором, пока не использовал remove(item) в первый раз, который разбил мой script на NotImplementedError. Поскольку я до сих пор не использовал поиск по индексу, я тем временем переключился на oset.

Если вы знаете о других реализациях PyPI, дайте мне знать в комментариях.

Ответ 6

Если вы используете упорядоченный набор для поддержания упорядоченного порядка, рассмотрите возможность использования реализации отсортированного набора из PyPI. Модуль sortedcontainers предоставляет SortedSet только для этой цели. Некоторые преимущества: реализация pure-Python, fast-as-C, покрытие 100% unit test, часы стресс-тестирования.

Установка из PyPI проста с помощью pip:

pip install sortedcontainers

Обратите внимание, что если вы не можете pip install, просто вытащите файлы sortedlist.py и sortedset.py из хранилища с открытым исходным кодом .

После установки вы можете просто:

from sortedcontainers import SortedSet
help(SortedSet)

Модуль sortedcontainers также поддерживает сравнение производительности с несколькими альтернативными реализациями.

Для комментария, который задал вопрос о типе данных пакета Python, в качестве альтернативы используется тип данных SortedList, который можно использовать для эффективного осуществления пакета.

Ответ 7

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

Ответ 8

Немного поздно к игре, но я написал класс setlist как часть collections-extended, который полностью реализует как Sequence и Set

>>> from collections_extended import setlist
>>> sl = setlist('abracadabra')
>>> sl
setlist(('a', 'b', 'r', 'c', 'd'))
>>> sl[3]
'c'
>>> sl[-1]
'd'
>>> 'r' in sl  # testing for inclusion is fast
True
>>> sl.index('d')  # so is finding the index of an element
4
>>> sl.insert(1, 'd')  # inserting an element already in raises a ValueError
ValueError
>>> sl.index('d')
4

GitHub: https://github.com/mlenzen/collections-extended

Документация: http://collections-extended.lenzm.net/ru/latest/

PyPI: https://pypi.python.org/pypi/collections-extended

Ответ 9

Там нет OrderedSet в официальной библиотеке. Я делаю исчерпывающий список всех структур данных для вашей справки.

DataStructure = {
    'Collections': {
        'Map': [
            ('dict', 'OrderDict', 'defaultdict'),
            ('chainmap', 'types.MappingProxyType')
        ],
        'Set': [('set', 'frozenset'), {'multiset': 'collection.Counter'}]
    },
    'Sequence': {
        'Basic': ['list', 'tuple', 'iterator']
    },
    'Algorithm': {
        'Priority': ['heapq', 'queue.PriorityQueue'],
        'Queue': ['queue.Queue', 'multiprocessing.Queue'],
        'Stack': ['collection.deque', 'queue.LifeQueue']
        },
    'text_sequence': ['str', 'byte', 'bytearray']
}

Ответ 10

ParallelRegression пакет предоставляет setList() упорядоченный класс заданий, который больше по методу, чем параметры, основанные на рецепте ActiveState. Он поддерживает все доступные методы для списков и большинство, если не все методы, доступные для наборов.

Ответ 11

Для многих целей достаточно просто отсортировать сортировку. Например

>>> s = set([0, 1, 2, 99, 4, 40, 3, 20, 24, 100, 60])
>>> sorted(s)
[0, 1, 2, 3, 4, 20, 24, 40, 60, 99, 100]

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

Ответ 12

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

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

if(not new_element in my_list):
    my_list.append(new_element)

Я не знаю, есть ли оговорки к этому простому подходу, но он решает мою проблему.

Ответ 13

Есть четыре типа заказов, которые могут потребоваться, я полагаю:

  • Упорядочено по ключу
  • Упорядочено по значению (я не слышал, чтобы кто-нибудь просил этого, хотя)
  • Упорядочено по времени модификации
  • Упорядочено по времени добавления

Я считаю, что collection.OrderedDict получает ваС# 4. Или вы можете удалить ключ и повторно добавить его для # 3.

Для # 1 вы, вероятно, должны проверить красно-черное дерево или treap:

Деревья Red-Black имеют низкую изменчивость во время работы (так что может быть лучше для интерактивных приложений), но не так быстро, как средняя средняя (что может быть лучше для пакетной обработки - treaps не реорганизуются сами, часто делая они быстро в среднем, но когда они реорганизуются, это может занять относительно долгое время).

Обе из них представляют собой структуры данных с реализациями на многих языках.

Ответ 14

Вы можете использовать reduce(), чтобы получить список уникальных значений в одной строке:

>>> mylist = [4, 1, 2, 1, 3, 2, 4, 1, 3, 2, 3, 1, 3, 2, 4]
>>> reduce(lambda a, b: b[0] in a and a or a + b, [[i] for i in mylist])
[4, 1, 2, 3]

Ответ 15

>>> a = {3, 4, 2, 6, 1, 7}
>>> type(a)
<class 'set'>
>>> sorted(a, reverse=True)
[7, 6, 4, 3, 2, 1]
>>> sorted(a)
[1, 2, 3, 4, 6, 7]