In [1]:
import random
The issue is the following: we have a list where one item is a category, and another one is a sortable value. We can easily sort the list appropriately, but we would also like to have a rank function, telling us the place of an item in any category.
In [12]:
mylist = [(random.randint(1,3),random.randint(1,100)) for x in range(20)]
mylist.sort()
mylist
Out[12]:
This rank function is easy to do procedural style but not that easy functional style. It can be done - we introduce a counter function with an appropriate reset
In [14]:
def new_counter ():
""" factory function for side-effect counter: count & reset on parameter changes
assume we have
counter = new_counter()
then counter(1) would yield 1,2,3....
however, as soon as the parameter of counter changes, the counter is reset. For example
counter = new_counter()
counter(1) # 1
counter(1) # 2
counter(1) # 3
counter(1) # 4
counter(2) # 1
counter(2) # 2
...
different counter generated from the same factory are independet
counter_a = new_counter()
counter_b = new_counter()
counter_a(1) # 1
counter_b(1) # 1
counter_a(1) # 2
counter_b(1) # 2
"""
counter = 0
old_val = 0
def f(new_val):
nonlocal counter
nonlocal old_val
if old_val != new_val:
counter = 0
old_val = new_val
counter +=1
return counter
return f
In [15]:
counter = new_counter()
mylist = [ (x[0],counter(x[0]),x[1]) for x in mylist]
mylist
Out[15]:
In [ ]: