<jupyter_start><jupyter_text>Lists<jupyter_code>print_scaling('collection.pop()',
              setup='collection = list(range({N}))')
print_scaling('collection.pop(0)',
              setup='collection = list(range({N}))')
print_scaling('collection.append(1)',
                        setup='collection = list(range({N}))')
print_scaling('collection.insert(0, 1)',
              setup='collection = list(range({N}))')
print_scaling('collection.insert(5000, 1)',
              setup='collection = list(range({N}))')
setup_code = '''
import random
random.seed(42)

collection = list(range({N}))
'''
print_scaling('collection.index(random.randint(0, {N}))',
              setup=setup_code)
from bisect import bisect_left

def index_bisect(a, x):
    'Locate the leftmost value exactly equal to x'
    i = bisect_left(a, x)
    if i != len(a) and a[i] == x:
        return i
    raise ValueError

setup_code = '''
from __main__ import index_bisect

import random
random.seed(42)

collection = list(range({N}))
'''
    
print_scaling('index_bisect(collection, random.randint(0, {N}))',
              setup=setup_code)<jupyter_output>N = 10000 t = 2.89 (us) | N = 20000 t = 3.46 (us) | N = 30000 t = 4.18 (us)<jupyter_text>Deque<jupyter_code>print_scaling('collection.pop()',
              setup='from collections import deque; collection = deque(range({N}))')
print_scaling('collection.popleft()',
              setup='from collections import deque; collection = deque(range({N}))')
print_scaling('collection.append(1)',
              setup='from collections import deque; collection = deque(range({N}))')
print_scaling('collection.appendleft(1)',
              setup='from collections import deque; collection = deque(range({N}))')
print_scaling('collection[0]',
              setup='from collections import deque; collection = deque(range({N}))')
print_scaling('collection[{N} - 1]',
              setup='from collections import deque; collection = deque(range({N}))')
print_scaling('collection[int({N}/2)]',
              setup='from collections import deque; collection = deque(range({N}))')<jupyter_output>N = 10000 t = 0.37 | N = 20000 t = 0.41 | N = 30000 t = 0.45
N = 10000 t = 0.37 | N = 20000 t = 0.42 | N = 30000 t = 0.43
N = 10000 t = 1.14 | N = 20000 t = 1.71 | N = 30000 t = 2.48<jupyter_text>Dictionaries<jupyter_code>setup_code = '''
from __main__ import random_string
collection = {{random_string(16) : i for i in range({N})}}
'''

print_scaling('"ITEM" in collection',
              setup=setup_code,
              sizes=[1000, 2000, 3000])

print_scaling('collection["ITEM"] if "ITEM" in collection else None',
              setup=setup_code,
              sizes=[1000, 2000, 3000])

print_scaling('collection["ITEM"] = 0',
              setup=setup_code,
              sizes=[1000, 2000, 3000])
setup_code = '''
from __main__ import random_string
collection = {{random_string(16) : i for i in range({N})}}
'''

print_scaling('"X"  * {N} in collection',
              setup=setup_code,
              sizes=[1000, 2000, 3000])
setup_code = '''
from uuid import uuid4
from collections import Counter
from __main__ import counter_defaultdict, counter_dict
import random

random.seed(42)
collection = [random.randint(0, 100) for i in range({N})]
'''
from collections import defaultdict
def counter_defaultdict(items):
    counter = defaultdict(int)
    for item in items:
        counter[item] += 1
    return counter

def counter_dict(items): 
    counter = {} 
    for item in items: 
        if item not in counter: 
            counter[item] = 0 
        else: 
            counter[item] += 1 
    return counter

print_scaling('Counter(collection)',
              setup=setup_code,
              sizes=[1000, 2000, 3000])

print_scaling('counter_defaultdict(collection)',
              setup=setup_code,
              sizes=[1000, 2000, 3000])

print_scaling('counter_dict(collection)',
              setup=setup_code,
              sizes=[1000, 2000, 3000])

from string import ascii_uppercase
import random
random.seed(42)

strings = [random_string(32) for i in range(10000)]
%timeit next(s for s in strings if s.startswith('AA'))
from patricia import trie
string_trie = trie(**{s: 0 for s in strings})
%timeit next(string_trie.iter('AA'))
setup_code = '''
from itertools import islice
from random import choice, seed, shuffle
from string import ascii_uppercase
seed(42)

# Initialize strings without letter 'A'
strings = [''.join(choice(ascii_uppercase.replace('A', '')) for i in range(32)) for j in range({N})]

# We make sure we only have 10 results that start with 'AA'
strings = ['AA' + s[2:] if i < 10 else s for i, s in enumerate(strings)]

# Randomization
shuffle(strings)
'''

print_scaling('[s for s in strings if s.startswith("AA")]',
              setup=setup_code,
              sizes=[10000, 20000, 30000],
              repeat=False, units='us')
setup_code = '''
from patricia import trie
from random import choice, seed, shuffle
from string import ascii_uppercase
from itertools import islice
seed(42)

# Initialize strings without letter 'A'
strings = [''.join(choice(ascii_uppercase.replace('A', '')) for i in range(32)) for j in range({N})]

# We make sure we only have 10 results that start with 'AA'
strings = ['AA' + s[2:] if i < 10 else s for i, s in enumerate(strings)]

# Randomization
shuffle(strings)
strings_dict = {{s: 0 for s in strings}}
strings_trie = trie(**strings_dict)
'''

print_scaling('list(strings_trie.iter("AA"))',
              setup=setup_code,
              sizes=[10000, 20000, 30000], units='us')<jupyter_output>N = 10000 t = 17.74 (us) | N = 20000 t = 17.48 (us) | N = 30000 t = 17.96 (us)<jupyter_text>Heaps<jupyter_code># Creating a heap
import heapq
collection = [10, 3, 3, 4, 5, 6]
heapq.heapify(collection)

# Extracting and inserting elements
heapq.heappop(collection)
heapq.heappush(collection, 1)
# The PriorityQueue class
from queue import PriorityQueue
collection = [10, 3, 3, 4, 5, 6]

queue = PriorityQueue()
for element in collection:
    queue.put(element)

queue.get(element)<jupyter_output><empty_output><jupyter_text>Caching<jupyter_code>def fibonacci(n):
    if n < 1:
        return 1
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

# Non-memoized version
%timeit fibonacci(20)<jupyter_output>1 loop, best of 3: 434 ms per loop<jupyter_text>Comprehensions and generators<jupyter_code>def loop(): 
    res = {} 
    for i in range(100000): 
        res[i] = i
    return res
 
def comprehension(): 
    return {i: i for i in range(100000)}

%timeit loop()
%timeit comprehension() 
def loop(): 
    res = [] 
    for i in range(100000): 
        res.append(i * i) 
    return sum(res) 
 
def comprehension(): 
    return sum([i * i for i in range(100000)]) 
 
def generator(): 
    return sum(i * i for i in range(100000)) 

%timeit loop() 
%timeit comprehension() 
%timeit generator() 
%load_ext memory_profiler
import os

numbers = range(1000000)

def map_comprehension(numbers):
    a = [n * 2 for n in numbers]
    b = [n ** 2 for n in a]
    c = [n ** 0.33 for n in b]
    return max(c)

%memit map_comprehension(numbers) 
def map_normal(numbers):
    a = map(lambda n: n * 2, numbers)
    b = map(lambda n: n ** 2, a)
    c = map(lambda n: n ** 0.33, b)
    return max(c)

%memit map_normal(numbers)<jupyter_output>peak memory: 71.04 MiB, increment: 0.00 MiB
{'fraction_non_alphanumeric': 0.13722826086956522, 'fraction_numerical': 0.051766304347826086, 'mean_word_length': 3.518723143032535, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '278009', 'license': 'MIT', 'n_tokens_mistral': 2756, 'n_tokens_neox': 2375, 'n_words': 680, 'path': 'Chapter02/.ipynb_checkpoints/Algorithms-checkpoint.ipynb', 'repo_name': 'VishalMewadaPackt/MasteringPython', 'size': '7360'}