Получить объект в sortedcontainers.SortedKeyList, используя другой ключ - PullRequest
0 голосов
/ 06 января 2020

Допустим, у меня есть Предмет со следующим определением:

Item(id: str, sequence: int)

id - случайная строка символов.

последовательность число, представляющее порядок, в котором Item был введен в структуру данных.


Я хотел организовать все Item объекты в некоторой структуре данных, которая поддерживает порядок Item на основе его sequence. Поэтому я использовал SortedKeyList с ключом они, установленным в sequence.

import sortedcontainers

items = sortedcontainers.SortedKeyList(key=lambda x: x.sequence)

Для большинства операций это работает нормально. Но проблема в том, что у меня есть операция, которая должна получить Item с указанием c id, но нет способа сделать это, используя указанный выше ключ.

Я бы хотел сделать что-то вроде:

items.add(Item('abc', 0))
items.add(Item('www', 1))
items.add(Item('zyx', 2))

# This should be the 2nd item added.
item = items['www']

Дополнительная информация :

Операция, которую я намеревался добавить, должна была бы иметь возможность вернуть N число Item начиная с указанного c id.

load_n_items_from_id(num: int, id: str) -> [Item]

Используя приведенный выше пример, этот метод должен вернуть следующий результат:

loaded = load_n_items_from_id(2, 'www')
# loaded should contain [Item('www', 1), Item('zyx', 2)]

Ответы [ 2 ]

0 голосов
/ 06 января 2020

Дано:

import sortedcontainers


class Item(object):
    def __init__(self, ident: str, sequence: int):
        self.ident = ident
        self.sequence = sequence

    def __repr__(self):
        return f"<Item id={self.ident} sequence={self.sequence}>"


items = sortedcontainers.SortedKeyList(key=lambda x: x.sequence)
items.add(Item("abc", 0))
items.add(Item("www", 1))
items.add(Item("zyx", 2))

Чтобы найти предмет, потребуется O (n) сложность, потому что вы ищете что-то, по чему он не отсортирован. Самый простой способ - это просто поиск элемента, мне нравится использовать next для этого, потому что это самый близкий эквивалент find с предикатом в python, и это лениво:

print(next((item for item in items if item.ident == "www"), None))

Дает :

<Item id=www sequence=1>

Я бы просто бросил его в вспомогательную функцию:

def find_by_ident(items, ident):
    return next((item for item in items if item.ident == ident), None)

Кроме того, если SortedKeyList инкапсулирован, вы также можете поддерживать простой диктат - кроме того, где ident -> item, если у вас sh также есть сложность O (1), но это может быть не так уж сложно или не стоить дополнительной памяти / сложности кода.

0 голосов
/ 06 января 2020

Вопрос, если я не ошибаюсь, просто заинтересован в поддержании порядка, в котором я вставляю элемент, если это так, мы можем просто использовать встроенную функцию OrderedDictionary https://docs.python.org/3/library/collections.html#ordereddict -объекты Вместо того, чтобы устанавливать отсортированные контейнеры через pip.

from collections import OrderedDict

items= OrderedDict()
#Items can be inserted according to your convenience either by loop or manually
items['abc']=0
items['www']=1
items['zyx']=2

print(items) #Prints dictionary in the given order

Не забудьте принять ответ, если он помог, если больше сомневаетесь, вы можете оставить комментарий. Фактически, я думаю, вы даже можете использовать обычный словарь (неупорядоченный), если все, что вам нужно, это значение соответствующего ключа, который вы уже дали при вводе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...