Skip to content

Instantly share code, notes, and snippets.

@IvanaGyro
Created April 17, 2019 16:59
Show Gist options
  • Save IvanaGyro/9d4a26fe9f4691bec0cdf7a0928ee8ab to your computer and use it in GitHub Desktop.
Save IvanaGyro/9d4a26fe9f4691bec0cdf7a0928ee8ab to your computer and use it in GitHub Desktop.
An other implementation of built-in generator `itertools.combinations` in pure Python. This function is faster than the official demostration in some cases.
def combinations(iterable, r, start=0):
'''
A generator that yields the combinations of the iterable object.
This generator has the same interface as the built-in generator
`itertools.combinations`. This function is faster than the official
demostration when the r is closed to the half of length of the input
iterable object.
'''
pool = tuple(iterable)
l = len(pool)
if r == 0 or l - start < r:
return
for i in range(start, l):
if r == 1:
yield (pool[i], )
else:
for res in combinations(pool, r - 1, i + 1):
yield (pool[i], ) + res
def offical_combinations(iterable, r):
'''
link: https://docs.python.org/zh-cn/3/library/itertools.html#itertools.combinations
'''
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = list(range(r))
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
task1 = \
'''
for c in combinations({}, 7):
pass
'''
task2 = \
'''
for c in offical_combinations({}, 7):
pass
'''
task3 = \
'''
for c in itertools.combinations({}, 7):
pass
'''
a7 = [1, 2, 3, 4, 5, 6, 7]
a10 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a13 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
if __name__ == '__main__':
import timeit
print(
timeit.timeit(task1.format('a7'), 'from combinations import combinations, a7', number = 1000),
timeit.timeit(task2.format('a7'), 'from combinations import offical_combinations, a7', number = 1000),
timeit.timeit(task3.format('a7'), 'from combinations import a7; import itertools', number = 1000),
)
print()
print(
timeit.timeit(task1.format('a10'), 'from combinations import combinations, a10', number = 1000),
timeit.timeit(task2.format('a10'), 'from combinations import offical_combinations, a10', number = 1000),
timeit.timeit(task3.format('a10'), 'from combinations import a10; import itertools', number = 1000),
)
print()
print(
timeit.timeit(task1.format('a13'), 'from combinations import combinations, a13', number = 1000),
timeit.timeit(task2.format('a13'), 'from combinations import offical_combinations, a13', number = 1000),
timeit.timeit(task3.format('a13'), 'from combinations import a13; import itertools', number = 1000),
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment