<commit_before>Itertools Idioms
================

Useful programming idioms with Python itertools.

Usage:

    >>> from itertools_idioms import idioms
    # Select keys using variable constraints
    >>> import operator
    >>> prices = {'cake': 50, 'bread': 20, 'pie': 100}
    >>> constraints = {'cake': (operator.lt, 60), 'bread': (operator.le, 20), 'pie': (operator.lt, 80)}
    >>> list(idioms.select(prices,constraints))
    ['cake', 'bread']

    # Random streams - infinite and constrained
    
    # Infinite random stream from your iterable
    >>> for i in idioms.random_stream(iterable): print i

    # Specific random streaming functions
    # This would keep going forever
    >>> for i in idioms.random_alphabets(): print i

    # This is constrained and stops when it encounters W
    >>> list(idioms.random_alphabets(sentinel='W'))
    ['i', 'o', 'z', 'y', 'd', 'Z', 'Y', 's', 'S', 'O', 'Q']

    # Infinite generator of random digits    
    >>> idioms.random_digits()
    <itertools.imap object at 0xa12f76c>
    
    # Would stop when encountering 8
    >>> list(idioms.random_digits(sentinel=8))
    [4, 2, 3, 2, 9, 5, 9, 3, 7, 7, 5, 5, 3, 5]
<commit_msg>Implicit support for comparison operators<commit_after>Itertools Idioms
================

Useful programming idioms with Python itertools.

Usage:

    >>> from itertools_idioms import idioms
    # Select keys using variable constraints

    >>> import operator
    >>> prices = {'cake': 50, 'bread': 20, 'pie': 100}
    >>> constraints = {'cake': (operator.lt, 60), 'bread': (operator.le, 20), 'pie': (operator.lt, 80)}
    >>> list(idioms.select(prices,constraints))
    ['cake', 'bread']

    # another option - use default operator module mapping
    # for constraints.
    >>> constraints = {'cake': ('<', 60), 'bread': ('<=', 20), 'pie': ('<', 80)}
    >>> list(idioms.select(prices,constraints, use_operator=True))
    ['cake', 'bread']
    
    # Random streams - infinite and constrained
    
    # Infinite random stream from your iterable
    >>> for i in idioms.random_stream(iterable): print i

    # Specific random streaming functions
    # This would keep going forever
    >>> for i in idioms.random_alphabets(): print i

    # This is constrained and stops when it encounters W
    >>> list(idioms.random_alphabets(sentinel='W'))
    ['i', 'o', 'z', 'y', 'd', 'Z', 'Y', 's', 'S', 'O', 'Q']

    # Infinite generator of random digits    
    >>> idioms.random_digits()
    <itertools.imap object at 0xa12f76c>
    
    # Would stop when encountering 8
    >>> list(idioms.random_digits(sentinel=8))
    [4, 2, 3, 2, 9, 5, 9, 3, 7, 7, 5, 5, 3, 5]

{'fraction_non_alphanumeric': 0.16590909090909092, 'fraction_numerical': 0.02803030303030303, 'mean_word_length': 3.438655462184874, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1478905', 'n_tokens_mistral': 925, 'n_tokens_neox': 833, 'n_words': 270}