Let's say I have an Item with the following definition:
Item(id: str, sequence: int)
id is a random string of characters.
sequence is the number representing the order that the Item
was put into the data structure.
I wanted to organize all Item
objects in some data structure that maintains the order of Item
based on its sequence
. So I used a SortedKeyList with they key set to sequence
.
import sortedcontainers
items = sortedcontainers.SortedKeyList(key=lambda x: x.sequence)
For most operations, this works fine. But the issue is that I have an operation that would need to get the Item
with a specific id
, but there is no way to do that using the key above.
I would like to do something like:
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']
Additional info :
The operation I intended to add would need to be able to return N number of Item
starting from a specific id
.
load_n_items_from_id(num: int, id: str) -> [Item]
Using the example above, this method should return the following result:
loaded = load_n_items_from_id(2, 'www')
# loaded should contain [Item('www', 1), Item('zyx', 2)]
The question if I am not wrong is simply interested in maintaining the order at which I am inserting the element, if that's the case we can simply make use of built in function OrderedDictionary https://docs.python.org/3/library/collections.html#ordereddict-objects rather than installing sortedcontainers via 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
Don't forget to accept the answer if it helped, if anymore doubts, you may drop the comment. Infact I guess you can even use normal dictionary(Unordered) if all you want is the value of the corresponding key which you already have given while giving the input.
Given:
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))
To find the item will require O(n) complexity, because you are searching by something that it is not sorted by. Simplest way is to just search for the item, I like using next
for this because it's the closest equivalent to a find
with a predicate in python, and it's lazy:
print(next((item for item in items if item.ident == "www"), None))
Gives:
<Item id=www sequence=1>
I would just throw it into a helper function:
def find_by_ident(items, ident):
return next((item for item in items if item.ident == ident), None)
Also, if the SortedKeyList
is encapsulated, you may also be able to maintain a simple dict along-side it where ident -> item
if you wish to have O(1) complexity here as well, but it may be no big deal or not worth the extra memory/code complexity.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.