@@ -1017,6 +1017,8 @@ which incur interpreter overhead.
10171017 "List unique elements, preserving order. Remember only the element just seen."
10181018 # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
10191019 # unique_justseen('ABBcCAD', str.lower) --> A B c A D
1020+ if key is None:
1021+ return map(operator.itemgetter(0), groupby(iterable))
10201022 return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
10211023
10221024
@@ -1136,24 +1138,6 @@ The following recipes have a more mathematical flavor:
11361138 n = n // p * (p - 1)
11371139 return n
11381140
1139- def nth_combination(iterable, r, index):
1140- "Equivalent to list(combinations(iterable, r))[index]"
1141- pool = tuple(iterable)
1142- n = len(pool)
1143- c = math.comb(n, r)
1144- if index < 0:
1145- index += c
1146- if index < 0 or index >= c:
1147- raise IndexError
1148- result = []
1149- while r:
1150- c, n, r = c*r//n, n-1, r-1
1151- while index >= c:
1152- index -= c
1153- c, n = c*(n-r)//n, n-1
1154- result.append(pool[-1-n])
1155- return tuple(result)
1156-
11571141
11581142.. doctest ::
11591143 :hide:
@@ -1577,20 +1561,6 @@ The following recipes have a more mathematical flavor:
15771561 >>> first_true(' ABC0DEF1' , ' 9' , str .isdigit)
15781562 '0'
15791563
1580- >>> population = ' ABCDEFGH'
1581- >>> for r in range (len (population) + 1 ):
1582- ... seq = list (combinations(population, r))
1583- ... for i in range (len (seq)):
1584- ... assert nth_combination(population, r, i) == seq[i]
1585- ... for i in range (- len (seq), 0 ):
1586- ... assert nth_combination(population, r, i) == seq[i]
1587-
1588- >>> iterable = ' abcde'
1589- >>> r = 3
1590- >>> combos = list (combinations(iterable, r))
1591- >>> all (nth_combination(iterable, r, i) == comb for i, comb in enumerate (combos))
1592- True
1593-
15941564
15951565.. testcode ::
15961566 :hide:
@@ -1617,6 +1587,24 @@ The following recipes have a more mathematical flavor:
16171587 for (a, _), (b, c) in pairwise(pairwise(iterable)):
16181588 yield a, b, c
16191589
1590+ def nth_combination(iterable, r, index):
1591+ "Equivalent to list(combinations(iterable, r))[index]"
1592+ pool = tuple(iterable)
1593+ n = len(pool)
1594+ c = math.comb(n, r)
1595+ if index < 0:
1596+ index += c
1597+ if index < 0 or index >= c:
1598+ raise IndexError
1599+ result = []
1600+ while r:
1601+ c, n, r = c*r//n, n-1, r-1
1602+ while index >= c:
1603+ index -= c
1604+ c, n = c*(n-r)//n, n-1
1605+ result.append(pool[-1-n])
1606+ return tuple(result)
1607+
16201608
16211609.. doctest ::
16221610 :hide:
@@ -1632,3 +1620,17 @@ The following recipes have a more mathematical flavor:
16321620
16331621 >>> list (triplewise(' ABCDEFG' ))
16341622 [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E'), ('D', 'E', 'F'), ('E', 'F', 'G')]
1623+
1624+ >>> population = ' ABCDEFGH'
1625+ >>> for r in range (len (population) + 1 ):
1626+ ... seq = list (combinations(population, r))
1627+ ... for i in range (len (seq)):
1628+ ... assert nth_combination(population, r, i) == seq[i]
1629+ ... for i in range (- len (seq), 0 ):
1630+ ... assert nth_combination(population, r, i) == seq[i]
1631+
1632+ >>> iterable = ' abcde'
1633+ >>> r = 3
1634+ >>> combos = list (combinations(iterable, r))
1635+ >>> all (nth_combination(iterable, r, i) == comb for i, comb in enumerate (combos))
1636+ True
0 commit comments