Вот я тут написал новую версию
>>> def f(s):
... if s == '':
... return s
... out = ''
... prev = ''
... n = 0
... for ch in s:
... if ch == prev or prev == '':
... pass
... else:
... out += prev + str(n)
... n = 0
... prev = ch
... n += 1
... out += prev + str(n)
... return out
...
>>> f('')
''
>>> f('a')
'a1'
>>> f('aa')
'a2'
>>> f('ab')
'a1b1'
>>> f('aaaarufnnbjff')
'a4r1u1f1n2b1j1f2'
>>>
Вот ещё одна, но она медленная. Зато самая короткая.
import itertools
def f(s):
return ''.join(c + str(len(tuple(g))) for c, g in itertools.groupby(s))
А вот тут замеры всех функций: двух твоих, моей старой (25 января 2012 года), моей новой и моей самой короткой.
#!/usr/bin/env python3
import timeit
def func1(s):
if not s: return ''
it = iter(s)
prev = next(it)
count = 1
out = ''
while True:
try:
curr = next(it)
if prev == curr: count += 1
else:
out += prev + str(count)
count = 1
prev = curr
except StopIteration:
out += prev + str(count)
break
return out
def func2(s):
if not s: return ''
out = ''
prev = s[0]
count = 1
ln = len(s)
for i in range(1,ln):
curr = s[i]
if prev == curr: count += 1
else:
out += prev + str(count)
count = 1
prev = curr
out += prev + str(count)
return out
def func3(s):
res = ''
state = 0
ch = ''
n = 0
i = 0
slen = len(s)
while i < slen:
c = s[i]
if state == 0: # first char
ch = c
n = 1
if i + 1 == slen:
res = ch + str(n)
state = 1
elif state == 1: # other char
if c == ch: # matched
n += 1
if i + 1 == slen:
res += ch + str(n)
else: # didn't match
res += ch + str(n)
ch = c
n = 0
i -= 1
i += 1
return res
def func4(s):
if s == '':
return s
out = ''
prev = ''
n = 0
for ch in s:
if ch == prev or prev == '':
pass
else:
out += prev + str(n)
n = 0
prev = ch
n += 1
out += prev + str(n)
return out
import itertools
def func5(s):
return ''.join(c + str(len(tuple(g))) for c, g in itertools.groupby(s))
def f1():
func1('aaabbbcde' * 100)
def f2():
func2('aaabbbcde' * 100)
def f3():
func3('aaabbbcde' * 100)
def f4():
func4('aaabbbcde' * 100)
def f5():
func5('aaabbbcde' * 100)
def main():
t1 = timeit.Timer('f1()', 'from __main__ import f1')
t2 = timeit.Timer('f2()', 'from __main__ import f2')
t3 = timeit.Timer('f3()', 'from __main__ import f3')
t4 = timeit.Timer('f4()', 'from __main__ import f4')
t5 = timeit.Timer('f5()', 'from __main__ import f5')
for t in t1, t2, t3, t4, t5:
print(t.repeat(3, 10000))
if __name__ == '__main__':
main()
Вывод
[guest@localhost rlecomp]$ ./rlecompcmp.py
[3.3369056259980425, 3.323838824995619, 3.326331812000717] # твоя итератор
[2.8052678310050396, 2.7940210589949857, 2.83161843400012] # твоя индексы
[5.913237972999923, 5.912506636996113, 5.872607308003353] # моя старая
[2.6772045339967008, 2.676720352996199, 2.6726658850020613] # моя новая
[4.964137271002983, 4.971889730004477, 4.978617688000668] # моя новая короткая
[guest@localhost rlecomp]$
Так же присоединяю архив, где есть моя новая функция, юнит-тесты для неё на pytest и измерительный скрипт со всеми функциями.