<jupyter_start><jupyter_text>1 Merging and Splitting Iterators Take several iterators as arguments and returns a single iterator<jupyter_code>from itertools import chain
for i in chain([1,2,3], ['a', 'b', 'c']):
    print(i, end=' ')
from itertools import *
def make_iterables_to_chain():
    yield [1, 2, 3]
    yield ['a', 'b', 'c']

for i in chain.from_iterable(make_iterables_to_chain()):
    print(i, end=' ')
print()<jupyter_output>1 2 3 a b c<jupyter_text>use *zip_longest* to zip a tuple<jupyter_code>from itertools import *
r1 = range(3)
r2 = range(2)
for r12 in zip(r1,r2):
    print(r12)
print()
print(list(zip_longest(r1,r2)))
print(list(zip_longest(r1,r2, fillvalue='a')))<jupyter_output>[(0, 0), (1, 1), (2, 'a')]<jupyter_text>**islice** returns selcted item by index<jupyter_code>from itertools import * 
print('Stop at 5')
for i in islice(range(100), 5):
    print(i, end =' ')
print('\n')

print('start at 5, and stop at 10')
for i in islice(range(100), 5, 10):
    print(i, end=' ')
print('\n')

print('by ten to 100')
for i in islice(range(100), 0,100, 10):
    print(i, end=' ')
print('\n')<jupyter_output>Stop at 5
0 1 2 3 4 

start at 5, and stop at 10
5 6 7 8 9 

by ten to 100
0 10 20 30 40 50 60 70 80 90<jupyter_text>**tee** returns several independent iterators(default to 2)<jupyter_code>from itertools import *
r = islice(count(), 5)
r1,r2 = tee(r)
print('r1', list(r1))
print('r2', list(r2))<jupyter_output>r1 [0, 1, 2, 3, 4]
r2 [0, 1, 2, 3, 4]<jupyter_text>2 Converting Inputs<jupyter_code>from itertools import *

values = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]

for i in starmap(lambda x, y: (x, y, x * y), values):
    print('{} * {} = {}'.format(*i))<jupyter_output>0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36<jupyter_text>3 Producing New Values<jupyter_code>from itertools import *

for i in zip(count(1), ['a', 'b', 'c']):
    print(i)<jupyter_output>(1, 'a')
(2, 'b')
(3, 'c')<jupyter_text>count() take start and step arguments<jupyter_code>import fractions
from itertools import *

start = fractions.Fraction(1, 3)
step = fractions.Fraction(1, 3)

for i in zip(count(start, step), ['a', 'b', 'c']):
    print('{}: {}'.format(*i))
from itertools import *

for i in zip(range(7), cycle(['a', 'b', 'c'])):
    print(i)
from itertools import *

for i in repeat('over-and-over', 5):
    print(i)<jupyter_output>over-and-over
over-and-over
over-and-over
over-and-over
over-and-over<jupyter_text>4 Filtering<jupyter_code>from itertools import *


def should_drop(x):
    print('Testing:', x)
    return x < 1


for i in dropwhile(should_drop, [-1, 0, 1, 2, -2]):
    print('Yielding:', i)<jupyter_output>Testing: -1
Testing: 0
Testing: 1
Yielding: 1
Yielding: 2
Yielding: -2<jupyter_text>dropwhile() does not filter every item of the input; after the condition is false the first time, all of the remaining items in the input are returned.<jupyter_code>from itertools import *


def should_take(x):
    print('Testing:', x)
    return x < 2


for i in takewhile(should_take, [-1, 0, 1, 2, -2]):
    print('Yielding:', i)<jupyter_output>Testing: -1
Yielding: -1
Testing: 0
Yielding: 0
Testing: 1
Yielding: 1
Testing: 2<jupyter_text>As soon as should_take() returns False, takewhile() stops processing the input. compress() offers another way to filter the contents of an iterable. Instead of calling a function, it uses the values in another iterable to indicate when to accept a value and when to ignore it.<jupyter_code>from itertools import *

every_third = cycle([False, False, True])
data = range(1, 10)

for i in compress(data, every_third):
    print(i, end=' ')
print()<jupyter_output>3 6 9<jupyter_text>5 Group Data<jupyter_code>import functools
from itertools import *
import operator
import pprint


@functools.total_ordering
class Point:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return '({}, {})'.format(self.x, self.y)

    def __eq__(self, other):
        return (self.x, self.y) == (other.x, other.y)

    def __gt__(self, other):
        return (self.x, self.y) > (other.x, other.y)


# Create a dataset of Point instances
data = list(map(Point,
                cycle(islice(count(), 3)),
                islice(count(), 7)))
print('Data:')
pprint.pprint(data, width=35)
print()
print('Grouped, unsorted:')
for k, g in groupby(data, operator.attrgetter('x')):
    print(k, list(g))
print()
# Sort the data
data.sort()
print('Sorted:')
pprint.pprint(data, width=35)
print()
print('Grouped, sorted:')
for k, g in groupby(data, operator.attrgetter('x')):
    print(k, list(g))
print()<jupyter_output>Grouped, sorted:
0 [(0, 0), (0, 3), (0, 6)]
1 [(1, 1), (1, 4)]
2 [(2, 2), (2, 5)]<jupyter_text>The input sequence needs to be sorted on the key value in order for the groupings to work out as expected. Nested for loops that iterate over multiple sequences can often be replaced with product(), which produces a single iterable whose values are the Cartesian product of the set of input values.<jupyter_code>from itertools import *
import pprint

FACE_CARDS = ('J', 'Q', 'K', 'A')
SUITS = ('H', 'D', 'C', 'S')

DECK = list(
    product(
        chain(range(2, 11), FACE_CARDS),
        SUITS,
    )
)

for card in DECK:
    print('{:>2}{}'.format(*card), end=' ')
    if card[1] == SUITS[-1]:
        print()<jupyter_output>2H  2D  2C  2S 
 3H  3D  3C  3S 
 4H  4D  4C  4S 
 5H  5D  5C  5S 
 6H  6D  6C  6S 
 7H  7D  7C  7S 
 8H  8D  8C  8S 
 9H  9D  9C  9S 
10H 10D 10C 10S 
 JH  JD  JC  JS 
 QH  QD  QC  QS 
 KH  KD  KC  KS 
 AH  AD  AC  AS
{'fraction_non_alphanumeric': 0.15385999640093576, 'fraction_numerical': 0.0455281626777038, 'mean_word_length': 3.9847533632286996, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '372216', 'license': 'MIT', 'n_tokens_mistral': 2371, 'n_tokens_neox': 2191, 'n_words': 688, 'path': 'Python-Standard-Library/Algorithm/Itertools.ipynb', 'repo_name': 'gaufung/CodeBase', 'size': '5557'}