Reputation: 2226
I am parsing an XML file, one of xml tag has a structure like this:
<product>
<item seq="division-sec">Division</item>
<item seq="dept-sec">Dept Info</item>
<item seq="label01">Label 01</item>
<item seq="label02">Label 02</item>
...
<item seq="labelN">Label N</item>
<item seq="date-mfg">27-11-2017</item>
<item seq="date-exp">28-11-2019</item>
</product>
I have written a generator function to access product labels in a sequence:
def product_labels(xmlpage):
#... parsed xml here
for item in xmlpage:
#-- process item for validation such as case sensitivity, etc
yield item # ("division-sec", "Division")
Now I'm looking for a function or may be an iterator class, which would allow me to get first, last, prev, next and search methods on it:
class ProdcutReader(object):
def __init__(self, product_labels):
self.product_labels = product_labels
def __iter__(self):
return self
def __prev__(self):
return prev(self.product_labels ) #-- Dont know how to do this :(
def __next__(self):
current = self.current(next(self.product_labels))
return current
def current(self, obj=None):
if not obj:
return self.first()
return obj
def first(self):
return list(self.product_labels)[0]
# search by label seq
def search(self, seq):
# Not sure if this is the correct way
for i in self.product_labels:
if i[0] == seq:
self.current(i)
return i
... # With some more methods (if search works I can have some more methods)
So assume I need to use that object, it should work like this:
from product_reader import ProdcutReader as Reader
>>>r = Reader(product_labels)
>>>r.first()
("division-sec", "Division")
>>>r.last()
("date-exp", "28-11-2019")
>>>r.current() # Let us say current is ("label01", "Label 01")
("label01", "Label 01")
>>>r.next() # or next(r)
("label02", "Label 02")
>>>r.prev()
("dept-sec", "Dept Info")
>>r.search("date-mfg") # This should also set the searched as r.current()
("date-mfg", "27-11-2017")
If I can get how to write for prev, next and search I will be able to write remaining methods like, first, last, current etc.
Upvotes: 1
Views: 128
Reputation: 27331
You apparently need random access to any element at any time. To my eyes, I don't see why you don't simply use a list.
If you need the current/next/previous functionality without having to keep track of a counter variable, you could still base your construct on a list:
class ProductReader(object):
def __init__(self, product_labels):
self.generator = product_labels
self.active_generator = self.generator()
self.element = None
self.cur = -1
def at_n(self, index):
if self.cur > index:
self.active_generator = self.generator()
while len(self.storage) < index+1:
self.element = next(self.active_generator)
self.cur = index
return self.element
def current(self):
if self.cur > -1:
return self.element
def last(self):
try:
while True:
self.element = next(self.generator)
self.cur += 1
except StopIteration:
return self.element
def first(self):
return self.at_n(0)
def next(self):
return self.at_n(self.cur+1)
__next__ = next
def prev(self):
return self.at_n(self.cur-1)
def search(self, query):
oldcur = self.cur
self.active_generator = self.generator()
for i, element in enumerate(self.generator()):
if query in element:
self.cur = i
self.element = element
return element
self.at_n(self.cur) # reset to old state
return None
Upvotes: 1