I came up with this code to convert a list of already ordered integers into a list of consecutive positive integers.
def consecutive_positive_inc(l):
"""
[0, 1, 1, 3, 4, 4, 5] -> [0, 1, 1, 2, 3, 3, 4]
"""
from collections import defaultdict
d = defaultdict(int)
for i in l:
d[i] = 1
for i, count in enumerate(d.values()):
for _ in range(count):
yield i
if __name__ == '__main__':
l = [-3, -2, -1, 0, 1, 1, 3, 4, 4, 5]
result = list(consecutive_positive_inc(l))
assert result == [0, 1, 2, 3, 4, 4, 5, 6, 6, 7]
Is it the best way to do it or something much simpler could be used?
CodePudding user response:
I think you've made it more complicated than it needs to be. Just keep a counter and bump when the number changes.
def consecutive_positive_inc(l):
"""
[0, 1, 1, 3, 4, 4, 5] -> [0, 1, 1, 2, 3, 3, 4]
"""
last = l[0]
idx = 0
for i in l:
if i != last:
idx = 1
last = i
yield idx
if __name__ == '__main__':
l = [-3, -2, -1, 0, 1, 1, 3, 4, 4, 5]
result = list(consecutive_positive_inc(l))
assert result == [0, 1, 2, 3, 4, 4, 5, 6, 6, 7]
CodePudding user response:
from itertools import groupby
def consecutive_inc(iterable, start=0):
"""
>>> list(consecutive_inc([0, 1, 1, 3, 4, 4, 5]))
[0, 1, 1, 2, 3, 3, 4]
"""
return (i for i, (_, g) in enumerate(groupby(iterable), start) for _ in g)
This uses O(1) space and works on arbitrary iterables.
CodePudding user response:
You can use a dict
like a mathematical set to keep track of how many unique numbers you have seen before:
def consecutive_positive_inc(l):
m = {}
r = []
for i in l:
m[i] = None
r.append(len(m) - 1)
return r
CodePudding user response:
You can do this in one line with a collections.Counter
:
>>> from collections import Counter
>>> def consecutive_positive_inc(arr):
... return [i for i, count in enumerate(Counter(arr).values()) for _ in range(count)]
...
>>> consecutive_positive_inc([0, 1, 1, 3, 4, 4, 5])
[0, 1, 1, 2, 3, 3, 4]