I need to operate on two separate infinite list of numbers, but could not find a way to generate, store and operate on it in python.
Can any one please suggest me a way to handle infinite Arithmetic Progession or any series and how to operate on them considering the fact the minimal use of memory and time.
Thanks every one for their suggestions in advance.
You are looking for a python generator instead:
def infinitenumbers():
count = 0
while True:
yield count
count += 1
The itertools package comes with a pre-built count generator.
>>> import itertools
>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> for i in itertools.islice(c, 5):
... print i
...
2
3
4
5
6
This is where the iterator comes in. You can't have an infinite list of numbers, but you can have an infinite iterator.
import itertools
arithmetic_progression = itertools.count(start,step) #from the python docs
The docs for Python2 can be found here
I have another python3 solution (read SICP chapter 3.5)
class Stream:
def __init__(self, head, tail):
self.head = head
self.tail = tail
self.memory = None
self.isDone = False
def car(self):
return self.head
def cdr(self):
if self.isDone:
return self.memory
self.memory = self.tail()
self.isDone = True
return self.memory
def __getitem__(self, pullFrom):
if pullFrom < 1 or self.memory == []:
return []
return [self.car()] + self.cdr()[pullFrom - 1]
def __repr__(self):
return "[" + repr(self.car()) + " x " + repr(self.tail) + "]"
def map(self, func):
if self.memory == []:
return []
return Stream(func(self.car()), lambda: Stream.map(self.cdr(), func))
def from_list(lst):
if lst == []:
return []
return Stream(lst[0], lambda:
Stream.from_list(lst[1:]))
def filter(self, pred):
if self.memory == []:
return []
elif pred(self.car()):
return Stream(self.car(), lambda: Stream.filter(self.cdr(), pred))
else:
return self.cdr().filter(pred)
def sieve(self):
return Stream(self.car(), lambda: self.cdr().filter(lambda n: n % self.car() > 0).sieve())
def foreach(self, action, pull = None):
if pull is None:
action(self.car())
self.cdr().foreach(action, pull)
elif pull <= 0:
return
else:
action(self.car())
self.cdr().foreach(action, pull-1)and run:
a = Stream(0, lambda: a.map((lambda x: x + 1)))
print(a[10])
which returns:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] .
But streams are lazily evaluated, so:
>>> a = Stream(0, lambda: a.map((lambda x: x + 1)))
>>> print(a)
prints:
[0 x [...]]
To create an object that acts like a "mutable" infinite list, you can overload the __getitem__ and __setitem__ methods in a class:
class infinite_list():
def __init__(self, func):
self.func = func
self.assigned_items = {}
def __getitem__(self, key):
if key in self.assigned_items:
return self.assigned_items[key]
else:
return self.func(key)
def __setitem__(self, key , value):
self.assigned_items[key] = value
Then, you can initialize the "infinite list" with a lambda expression and modify an item in the list:
infinite_thing = infinite_list(lambda a: a*2)
print(infinite_thing[1]) #prints "2"
infinite_thing[1] = infinite_thing[2]
print(infinite_thing[1]) #prints "4"
Similarly, it is possible to create an "infinite dictionary" that provides a default value for each missing key.
Perhaps the natural way to generate an infinite series is using a generator:
def arith(a, d):
while True:
yield a
a += d
This can be used like so:
print list(itertools.islice(arith(10, 2), 100))
My solution is:
from hofs import *
def cons_stream(head,tail):
return [head,tail,False,False]
def stream_cdr(strm):
if strm[2]:
return strm[3]
strm[3] = strm[1]()
strm[2] = True
return strm[3]
def show_stream(stream, num = 10):
if empty(stream):
return []
if num == 0:
return []
return adjoin(stream[0], show_stream(stream_cdr(stream), num - 1))
def add_streams(a , b):
if empty(a):
return b
if empty(b):
return a
return cons_stream(a[0] + b[0] , lambda : add_streams( stream_cdr(a), stream_cdr(b)))
def stream_filter( pred , stream ):
if empty(stream):
return []
if pred(stream[0]):
return cons_stream(stream[0], lambda : stream_filter(pred, stream_cdr(stream)))
else:
return stream_filter( pred , stream_cdr( stream ))
def sieve(stream):
return cons_stream(stream[0] , lambda : sieve(stream_filter(lambda x : x % stream[0] > 0 , stream_cdr(stream))))
ones = cons_stream(1, lambda : ones)
integers = cons_stream(1, lambda : add_streams(ones, integers))
primes = sieve(stream_cdr(integers))
print(show_stream(primes))
Copy the Python code above.
When I tried it, i got [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] which is 10 of an infinite list of primes.
You need hofs.py to be
def empty(data):
return data == []
def adjoin(value,data):
result = [value]
result.extend(data)
return result
def map(func, data):
if empty(data):
return []
else:
return adjoin(func(data[0]), map(func, data[1:]))
def keep(pred, data):
if empty(data):
return []
elif pred(data[0]):
return adjoin( data[0] , keep(pred, data[1:]))
else:
return keep(pred, data[1:])
I assume you want a list of infinite numbers within a range. I have a similar problem, and here is my solution:
c = 0
step = 0.0001 # the difference between the numbers
limit = 100 # The upper limit
myInfList = []
while c <= limit:
myInfList.append(c)
c = c + step
print(myInfList)
Related
'int' Object Not Callable Heap Sort Function
Im trying to create a function that return a sorted list but im getting the following error: "new_value = sort_heap.deleteMin() 'int' object is not callable"
This is the code:
class MinHeap:
def __init__(self):
self.heap=[]
def __str__(self):
return f'{self.heap}'
__repr__=__str__
def parent(self,index):
# -- YOUR CODE STARTS HERE
if index>len(self) or index<=1:
return None
else:
return self.heap[index//2-1]
def leftChild(self,index):
# -- YOUR CODE STARTS HERE
if index<1 or 2*index>len(self):
return None
else:
return self.heap[2*index-1]
def rightChild(self,index):
if index<1 or 2*index>len(self):
return None
else:
return self.heap[2*index-1]
def __len__(self):
return len(self.heap)
def insert(self,x):
self.heap.append(x)
current = len(self)
while self.parent(current) is not None and self.parent(current)>x:
self.heap[current-1], self.heap[current//2-1] = self.heap[current//2-1], self.heap[current-1]
current = current//2
#property
def deleteMin(self):
if len(self)==0:
return None
elif len(self)==1:
out=self.heap[0]
self.heap=[]
return out
deleted = self.heap[0]
current = 1
self.heap[0] = self.heap[len(self)-1]
x = self.heap.pop()
moved_value = self.heap[0]
while self.leftChild(current) is not None:
left=self.leftChild(current)
right=self.rightChild(current)
if right is not None:
if left<=right and left<moved_value:
self.heap[current-1], self.heap[current*2] = self.heap[current*2], self.heap[current-1]
current = current *2
elif left>right and right<moved_value:
self.heap[current-1], self.heap[current*2] = self.heap[current*2], self.heap[current-1]
current = (current*2) + 1
else:
break
else:
if left<moved_value:
self.heap[current-1], self.heap[(current*2)-1] = self.heap[(current*2)-1], self.heap[current-1]
current = current*2
else:
break
return deleted
def heapSort(numList):
'''
>>> heapSort([9,7,4,1,2,4,8,7,0,-1])
[-1, 0, 1, 2, 4, 4, 7, 7, 8, 9]
'''
sort_heap = MinHeap()
for i in range (len(numList)):
sort_heap.insert(numList[i])
sortedList= []
lenght=len(numList)
while lenght >0:
new_value = sort_heap.deleteMin()
sortedList.append(new_value)
lenght -= 1
return sortedList
The MinHeap class is a given but I'm allow to modify it. Could Someone please help? Thanks
Seeing your (btw wrong formatted code, please redo the formatting) code I can see, that deleteMin is a #property and not a class method. Therefore you shuld write:
new_value = sort_heap.deleteMin
# ^ You see, no brackets here
I'm trying to make the following function completely tail recursive, e.g. get that pesky for loop out of there. Reason being is that I'm trying to easily convert the solution to an iterative one involving the use of an explicit stack. Please advise.
def permutations(A):
P = []
P2 = []
permutations_recursive(A, [], P)
permutations_tail_recursive(A, [], P2, 0)
print(P2)
return P
def permutations_recursive(first, last, perms):
if len(first) == 0:
perms.append(last)
else:
for i in range(len(first)):
permutations_recursive(
first[:i] + first[i+1:],
last + [first[i]],
perms)
Close iterative analog:
def permutations(A):
P = []
permutationsI(A, P)
print(P)
def permutationsI(A, perms):
stack = [(A, [])]
while len(stack):
first, last = stack.pop()
if len(first):
for i in range(len(first)):
stack.append((first[:i] + first[i+1:],last + [first[i]]))
else:
perms.append(last)
permutations([1,2,3])
>>[[3, 2, 1], [3, 1, 2], [2, 3, 1], [2, 1, 3], [1, 3, 2], [1, 2, 3]]
A fully recursive function should be:
def permutations_comp_recursive(first, last, perms, i):
if len(first) == 0:
perms.append(last)
elif i == len(first):
pass
else:
permutations_comp_recursive(first, last, perms, i+1)
if first:
permutations_comp_recursive(
first[:i]+first[i+1:],
last + [first[i]],
perms, 0)
For good performance i recommand numpy solutions.
Edit 1: Now the following should be tail-recursive, with the use of list comprehensions. This uses a workarount for tail-recursion in python (and the last 2 arguments were omitted - the result is passed as return value):
import itertools as it
class Recurse(Exception):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
def recurse(*args, **kwargs):
raise Recurse(*args, **kwargs)
def tail_recursive(f):
def decorated(*args, **kwargs):
while True:
try:
return f(*args, **kwargs)
except Recurse as r:
args = r.args
kwargs = r.kwargs
continue
return decorated
#tail_recursive
def permutations_tail_recursive(first, last, direct=False):
if len(first) == 0 or not all(first):
return last
else:
l = len(first[0]) if direct else len(first)
if last:
return recurse([fi[:i]+fi[i+1:] for fi, i in it.product(first, range(l))],
[last[j] + first[j][i] for j, i in it.product(range(len(last)), range(l))], True)
else:
return recurse([first[:i]+first[i+1:] for i in range(l)],
[first[i] for i in range(l)], True)
This is not optimised and uses loops. Im not sure if this and the code without loop above can be combined - might look into it again.
itertools.permutations can be used for this application.
Given the following scenario:
import string
UPPERCASE_ALPHABET = list(string.ascii_uppercase)
LOWERCASE_ALPHABET = list(string.ascii_lowercase)
How to create a cyclic loop over the alphabet jumping N positions?
Example 1:
letter = a, jump = 5
Result: f
Example 2:
letter = z, jump = 5
Result: e
So far, I got:
import string
UPPERCASE_ALPHABET = list(string.ascii_uppercase)
LOWERCASE_ALPHABET = list(string.ascii_lowercase)
def forward(letter, jump):
alphabet = LOWERCASE_ALPHABET if letter.islower() else UPPERCASE_ALPHABET
index = alphabet.index(letter)
count = 0
while True:
if count == jump:
return alphabet[index]
if index == len(alphabet):
index = 0
index += 1
count += 1
print forward('a', 5)
print forward('z', 5)
But it doesn't look Pythonic at all...
Is there a better and Pythonic way of doing this? Maybe using chr(ord('N') + position) ?
I think you had the right idea with ord and chr:
import string
def forward(letter, jump):
if letter.islower():
start_character = ord('a')
else:
start_character = ord('A')
start = ord(letter) - start_character
offset = ((start + jump) % 26) + start_character
result = chr(offset)
return result
print forward('a', 5)
print forward('z', 5)
print forward('z', 1)
print forward('a', 26)
print forward('A', 5)
print forward('Z', 5)
print forward('Z', 1)
print forward('A', 26)
Output
f
e
a
a
F
E
A
A
I'd write a custom iterator class to encapsulate itertools.cycle() and provide a skip() functionality, e.g.:
import itertools
class CyclicSkipIterator(object):
def __init__(self, iterable):
self._iterator = itertools.cycle(iterable)
def __iter__(self):
return self
def next(self): # use __next__ on Python 3.x
return next(self._iterator)
def skip(self, number=1):
for i in xrange(number): # use range() on Python 3.x
next(self._iterator)
Then you can do exactly what you wanted with it:
import string
LOWERCASE_ALPHABET = list(string.ascii_lowercase)
lower_iter = CyclicSkipIterator(LOWERCASE_ALPHABET)
print(next(lower_iter)) # a
lower_iter.skip(4) # skip next 4 letters: b, c, d, e
print(next(lower_iter)) # f
lower_iter.skip(19) # skip another 19 letters to arrive at z
print(next(lower_iter)) # z
lower_iter.skip(4) # skip next 4 letters: a, b, c, d
print(next(lower_iter)) # e
You can add even more functionality if you wanted to, like reversing, switching iterables mid-iteration etc.
UPDATE: If you want to jump to a specific element in the list, you can add a method for that to the CyclicSkipIterator:
class CyclicSkipIterator(object):
def __init__(self, iterable):
self._iterator = itertools.cycle(iterable)
def __iter__(self):
return self
def __next__(self): # use __next__ on Python 3.x
return next(self._iterator)
def skip(self, number=1):
for _ in range(number): # use range() on Python 3.x
next(self._iterator)
def skip_to(self, element, max_count=100): # max_count protects against endless cycling
max_count = max(1, max_count) # ensure at least one iteration
for _ in range(max_count): # use range() on Python 3.x
e = next(self._iterator)
if element == e:
break
Then you can skip_to whatever letter you want:
import string
LOWERCASE_ALPHABET = list(string.ascii_lowercase)
lower_iter = CyclicSkipIterator(LOWERCASE_ALPHABET)
print(next(lower_iter)) # a
lower_iter.skip(4) # skip 4 letters: b, c, d, e
print(next(lower_iter)) # f
lower_iter.skip_to("y") # skip all letters up to y
print(next(lower_iter)) # z
lower_iter.skip(4) # skip 4 letters: a, b, c, d
print(next(lower_iter)) # e
class CyclicIterator:
def __init__(self,lst):
self.lst=lst
self.i=0
def __iter__(self):
return self
def __next__(self):
result=self.lst[self.i % len(self.lst)]
self.i+=3 #increasing by 3
return result
class that has iter() and next() meets iterator protocol. creating an instance of this iterator class
iter_cycle=CyclicIterator('abcdefghiijklmnnoprstuvyz')
numbers=range(1,27,3) # 26 letters increases by 3
list(zip(list(numbers),iter_cycle))
I have a list which I want to sort by multiple keys, like:
L = [ ... ]
L.sort(key = lambda x: ( f(x), g(x) ))
This works fine. However, this results with unnecessary calls to g, which I would like to avoid (for being potentially slow). In other words, I want to partially and lazily evaluate the key.
For example, if f is unique over L (i.e. len(L) == len(set(map(f,L)))) no calls to g should be made.
What would be the most elegant/pythonic way to do this?
One way I can think of is to define a custom cmp function (L.sort(cmp=partial_cmp)), but IMO this is less elegant and more complicated than using the key parameter.
Another way would be to define a key-wrapper class which takes a generator expression to generate the different parts of the key, and override the comparison operators to compare one-by-one. However, I'm feeling there must be a simpler way...
EDIT: I'm interested in a solution for the general problem of sorting by multiple functions, not only two as in my example above.
You can try using itertools.groupby:
result = []
for groupKey, group in groupby(sorted(L, key=f), key=f):
sublist = [y for y in group]
if len(sublist) > 1:
result += sorted(sublist, key=g)
else:
result += sublist
Another possibility, even less elegant, but in place:
L.sort(key = f)
start = None
end = None
for i,x in enumerate(L):
if start == None:
start = i
elif f(x) == f(L[start]):
end = i
elif end == None:
start = i
else:
L[start:end+1] = sorted(L[start:end+1], key=g)
start = None
if start != None and end != None:
L[start:end+1] = sorted(L[start:end+1], key=g)
First version generalized to any number of functions:
def sortBy(l, keyChain):
if not keyChain:
return l
result = []
f = keyChain[0]
for groupKey, group in groupby(sorted(l, key=f), key=f):
sublist = [y for y in group]
if len(sublist) > 1:
result += sortBy(sublist, keyChain[1:])
else:
result += sublist
return result
The second version generalized to any number of functions (not fully in place though):
def subSort(l, start, end, keyChain):
part = l[start:end+1]
sortBy(part, keyChain[1:])
l[start:end+1] = part
def sortBy(l, keyChain):
if not keyChain:
return
f = keyChain[0]
l.sort(key = f)
start = None
end = None
for i,x in enumerate(l):
if start == None:
start = i
elif f(x) == f(l[start]):
end = i
elif end == None:
start = i
else:
subSort(l, start, end, keyChain)
start = i
end = None
if start != None and end != None:
subSort(l, start, end, keyChain)
Given a function, you could create a LazyComparer class like this:
def lazy_func(func):
class LazyComparer(object):
def __init__(self, x):
self.x = x
def __lt__(self, other):
return func(self.x) < func(other.x)
def __eq__(self, other):
return func(self.x) == func(other.x)
return lambda x: LazyComparer(x)
To make a lazy key function out of multiple functions, you could create a utility function:
def make_lazy(*funcs):
def wrapper(x):
return [lazy_func(f)(x) for f in funcs]
return wrapper
And together they could be used like this:
def countcalls(f):
"Decorator that makes the function count calls to it."
def _f(*args, **kwargs):
_f._count += 1
return f(*args, **kwargs)
_f._count = 0
return _f
#countcalls
def g(x): return x
#countcalls
def f1(x): return 0
#countcalls
def f2(x): return x
def report_calls(*funcs):
print(' | '.join(['{} calls to {}'.format(f._count, f.func_name)
for f in funcs]))
L = range(10)[::-1]
L.sort(key=make_lazy(f1, g))
report_calls(f1, g)
g._count = 0
L.sort(key=make_lazy(f2, g))
report_calls(f2, g)
which yields
18 calls to f1 | 36 calls to g
36 calls to f2 | 0 calls to g
The #countcalls decorator above is used to connfirm that when f1 returns a lot
of ties, g is called to break the ties, but when f2 returns distinct values,
g does not get called.
NPE's solution adds memoization within the Key class. With the solution above,
you could add memoization outside (independent of) the LazyComparer class:
def memo(f):
# Author: Peter Norvig
"""Decorator that caches the return value for each call to f(args).
Then when called again with same args, we can just look it up."""
cache = {}
def _f(*args):
try:
return cache[args]
except KeyError:
cache[args] = result = f(*args)
return result
except TypeError:
# some element of args can't be a dict key
return f(*args)
_f.cache = cache
return _f
L.sort(key=make_lazy(memo(f1), memo(g)))
report_calls(f1, g)
which results in fewer calls to g:
10 calls to f1 | 10 calls to g
You could use a key object that would lazily evaluate and cache g(x):
class Key(object):
def __init__(self, obj):
self.obj = obj
self.f = f(obj)
#property
def g(self):
if not hasattr(self, "_g"):
self._g = g(self.obj)
return self._g
def __cmp__(self, rhs):
return cmp(self.f, rhs.f) or cmp(self.g, rhs.g)
Here is an example of use:
def f(x):
f.count += 1
return x // 2
f.count = 0
def g(x):
g.count += 1
return x
g.count = 0
L = [1, 10, 2, 33, 45, 90, 3, 6, 1000, 1]
print sorted(L, key=Key)
print f.count, g.count
Is there anyway to make a python list iterator to go backwards?
Basically i have this
class IterTest(object):
def __init__(self, data):
self.data = data
self.__iter = None
def all(self):
self.__iter = iter(self.data)
for each in self.__iter:
mtd = getattr(self, type(each).__name__)
mtd(each)
def str(self, item):
print item
next = self.__iter.next()
while isinstance(next, int):
print next
next = self.__iter.next()
def int(self, item):
print "Crap i skipped C"
if __name__ == '__main__':
test = IterTest(['a', 1, 2,3,'c', 17])
test.all()
Running this code results in the output:
a
1
2
3
Crap i skipped C
I know why it gives me the output, however is there a way i can step backwards in the str() method, by one step?
EDIT
Okay maybe to make this more clear. I don't want to do a full reverse, basically what i want to know if there is an easy way to do the equivalent of a bidirectional iterator in python?
No, in general you cannot make a Python iterator go backwards. However, if you only want to step back once, you can try something like this:
def str(self, item):
print item
prev, current = None, self.__iter.next()
while isinstance(current, int):
print current
prev, current = current, self.__iter.next()
You can then access the previous element any time in prev.
If you really need a bidirectional iterator, you can implement one yourself, but it's likely to introduce even more overhead than the solution above:
class bidirectional_iterator(object):
def __init__(self, collection):
self.collection = collection
self.index = 0
def next(self):
try:
result = self.collection[self.index]
self.index += 1
except IndexError:
raise StopIteration
return result
def prev(self):
self.index -= 1
if self.index < 0:
raise StopIteration
return self.collection[self.index]
def __iter__(self):
return self
Am I missing something or couldn't you use the technique described in the Iterator section in the Python tutorial?
>>> class reverse_iterator:
... def __init__(self, collection):
... self.data = collection
... self.index = len(self.data)
... def __iter__(self):
... return self
... def next(self):
... if self.index == 0:
... raise StopIteration
... self.index = self.index - 1
... return self.data[self.index]
...
>>> for each in reverse_iterator(['a', 1, 2, 3, 'c', 17]):
... print each
...
17
c
3
2
1
a
I know that this doesn't walk the iterator backwards, but I'm pretty sure that there is no way to do that in general. Instead, write an iterator that walks a discrete collection in reverse order.
Edit you can also use the reversed() function to get a reversed iterator for any collection so that you don't have to write your own:
>>> it = reversed(['a', 1, 2, 3, 'c', 17])
>>> type(it)
<type 'listreverseiterator'>
>>> for each in it:
... print each
...
17
c
3
2
1
a
An iterator is by definition an object with the next() method -- no mention of prev() whatsoever. Thus, you either have to cache your results so you can revisit them or reimplement your iterator so it returns results in the sequence you want them to be.
Based on your question, it sounds like you want something like this:
class buffered:
def __init__(self,it):
self.it = iter(it)
self.buf = []
def __iter__(self): return self
def __next__(self):
if self.buf:
return self.buf.pop()
return next(self.it)
def push(self,item): self.buf.append(item)
if __name__=="__main__":
b = buffered([0,1,2,3,4,5,6,7])
print(next(b)) # 0
print(next(b)) # 1
b.push(42)
print(next(b)) # 42
print(next(b)) # 2
You can enable an iterator to move backwards by following code.
class EnableBackwardIterator:
def __init__(self, iterator):
self.iterator = iterator
self.history = [None, ]
self.i = 0
def next(self):
self.i += 1
if self.i < len(self.history):
return self.history[self.i]
else:
elem = next(self.iterator)
self.history.append(elem)
return elem
def prev(self):
self.i -= 1
if self.i == 0:
raise StopIteration
else:
return self.history[self.i]
Usage:
>>> prev = lambda obj: obj.prev() # A syntactic sugar.
>>>
>>> a = EnableBackwardIterator(iter([1,2,3,4,5,6]))
>>>
>>> next(a)
1
>>> next(a)
2
>>> a.next() # The same as `next(a)`.
3
>>> prev(a)
2
>>> a.prev() # The same as `prev(a)`.
1
>>> next(a)
2
>>> next(a)
3
>>> next(a)
4
>>> next(a)
5
>>> next(a)
6
>>> prev(a)
5
>>> prev(a)
4
>>> next(a)
5
>>> next(a)
6
>>> next(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
You can wrap your iterator in an iterator helper to enable it to go backward. It will store the iterated values in a collection and reuse them when going backwards.
class MemoryIterator:
def __init__(self, iterator : Iterator):
self._iterator : Iterator = iterator
self._array = []
self._isComplete = False
self._pointer = 0
def __next__(self):
if self._isComplete or self._pointer < len(self._array):
if self._isComplete and self._pointer >= len(self._array):
raise StopIteration
value = self._array[self._pointer]
self._pointer = self._pointer + 1
return value
try:
value = next(self._iterator)
self._pointer = self._pointer + 1
self._array.append(value)
return value
except StopIteration:
self._isComplete = True
def prev(self):
if self._pointer - 2 < 0:
raise StopIteration
self._pointer = self._pointer - 1
return self._array[self._pointer - 1]
The usage can be similar to this one:
my_iter = iter(my_iterable_source)
memory_iterator = MemoryIterator(my_iter)
try:
if forward:
print(next(memory_iterator))
else:
print(memory_iterator.prev())
except StopIteration:
pass
I came here looking for a bi-directional iterator. Not sure if this is what the OP was looking for but it is one way to make a bi-directional iterator—by giving it an attribute to indicate which direction to go in next:
class BidirectionalCounter:
"""An iterator that can count in two directions (up
and down).
"""
def __init__(self, start):
self.forward = True
# Code to initialize the sequence
self.x = start
def __iter__(self):
return self
def __next__(self):
if self.forward:
return self.next()
else:
return self.prev()
def reverse(self):
self.forward = not self.forward
def next(self):
"""Compute and return next value in sequence.
"""
# Code to go forward
self.x += 1
return self.x
def prev(self):
"""Compute and return previous value in sequence.
"""
# Code to go backward
self.x -= 1
return self.x
Demo:
my_counter = BidirectionalCounter(10)
print(next(my_counter))
print(next(my_counter))
my_counter.reverse()
print(next(my_counter))
print(next(my_counter))
Output:
11
12
11
10
i think thi will help you to solve your problem
class TestIterator():
def __init__(self):`
self.data = ["MyData", "is", "here","done"]
self.index = -1
#self.index=len(self.data)-1
def __iter__(self):
return self
def next(self):
self.index += 1
if self.index >= len(self.data):
raise StopIteration
return self.data[self.index]
def __reversed__(self):
self.index = -1
if self.index >= len(self.data):
raise StopIteration
return self.data[self.index]
r = TestIterator()
itr=iter(r)
print (next(itr))
print (reversed(itr))
ls = [' a', 5, ' d', 7, 'bc',9, ' c', 17, '43', 55, 'ab',22, 'ac']
direct = -1
l = ls[::direct]
for el in l:
print el
Where direct is -1 for reverse or 1 for ordinary.
Python you can use a list and indexing to simulate an iterator:
a = [1,2,3]
current = 1
def get_next(a):
current = a[a.index(current)+1%len(a)]
return current
def get_last(a):
current = a[a.index(current)-1]
return current # a[-1] >>> 3 (negative safe)
if your list contains duplicates then you would have to track your index separately:
a =[1,2,3]
index = 0
def get_next(a):
index = index+1 % len(a)
current = a[index]
return current
def get_last(a):
index = index-1 % len(a)
current = a[index-1]
return current # a[-1] >>> 3 (negative safe)
An iterator that visits the elements of a list in reverse order:
class ReverseIterator:
def __init__(self,ls):
self.ls=ls
self.index=len(ls)-1
def __iter__(self):
return self
def __next__(self):
if self.index<0:
raise StopIteration
result = self.ls[self.index]
self.index -= 1
return result
I edited the python code from dilshad (thank you) and used the following Python 3 based code to step between list item's back and forth or let say bidirectional:
# bidirectional class
class bidirectional_iterator:
def __init__(self):
self.data = ["MyData", "is", "here", "done"]
self.index = -1
def __iter__(self):
return self
def __next__(self):
self.index += 1
if self.index >= len(self.data):
raise StopIteration
return self.data[self.index]
def __reversed__(self):
self.index -= 1
if self.index == -1:
raise StopIteration
return self.data[self.index]
Example:
>>> r = bidirectional_iterator()
>>> itr=iter(r)
>>> print (next(itr))
MyData
>>> print (next(itr))
is
>>> print (next(itr))
here
>>> print (reversed(itr))
is
>>> print (reversed(itr))
MyData
>>> print (next(itr))
is
This is a common situation when we need to make an iterator go back one step. Because we should get the item and then check if we should break the loop. When breaking the loop, the last item may be requied in later usage.
Except of implementing an iteration class, here is a handy way make use of builtin itertools.chain :
from itertools import chain
>>> iterator = iter(range(10))
>>> for i in iterator:
... if i <= 5:
... print(i)
... else:
... iterator = chain([i], iterator) # push last value back
... break
...
0
1
2
3
4
5
>>> for i in iterator:
... print(i)
...
6
7
8
9
please see this function made by Morten Piibeleht. It yields a (previous, current, next) tuple for every element of an iterable.
https://gist.github.com/mortenpi/9604377