itertools & functools
itertools: lazy iteration ไม่ต้องพึ่ง dependencies
หัวข้อที่มีชื่อว่า “itertools: lazy iteration ไม่ต้องพึ่ง dependencies”เวลาต้องการ collection utility ฝั่ง TypeScript มักหยิบ Lodash มาใช้ ส่วน Python มี itertools ติดมาใน standard library อยู่แล้ว และทำงานแบบ lazy คือผลิตค่าตอนที่ต้องใช้ ไม่สร้าง list กลางทางทิ้งไว้ จุดนี้สำคัญมากเมื่อเจอ dataset ขนาดใหญ่
chain — รวม iterables หลายตัว
หัวข้อที่มีชื่อว่า “chain — รวม iterables หลายตัว”// TypeScript / Lodashimport _ from 'lodash';const result = _.concat([1, 2], [3, 4], [5]);// หรือ spread:const result2 = [...[1, 2], ...[3, 4], ...[5]];console.log(result); // [1, 2, 3, 4, 5]import itertools
result = list(itertools.chain([1, 2], [3, 4], [5]))print(result) # [1, 2, 3, 4, 5]
# chain.from_iterable — flatten หนึ่งระดับnested = [[1, 2], [3, 4], [5]]flat = list(itertools.chain.from_iterable(nested))print(flat) # [1, 2, 3, 4, 5]count — infinite counter
หัวข้อที่มีชื่อว่า “count — infinite counter”// TypeScript — manual counter หรือ generatorfunction* count(start = 0, step = 1) { let n = start; while (true) { yield n; n += step; }}
const gen = count(10, 2);const result = Array.from({ length: 4 }, () => gen.next().value);console.log(result); // [10, 12, 14, 16]import itertools
counter = itertools.count(10, 2) # infinite lazy counterresult = [next(counter) for _ in range(4)]print(result) # [10, 12, 14, 16]
# islice — รับ N items จาก infinite iterator ได้อย่างปลอดภัยfirst_five = list(itertools.islice(itertools.count(1), 5))print(first_five) # [1, 2, 3, 4, 5]groupby — จัดกลุ่ม items ที่ต่อเนื่องกัน
หัวข้อที่มีชื่อว่า “groupby — จัดกลุ่ม items ที่ต่อเนื่องกัน”groupby ทำงานคล้าย GROUP BY ของ SQL แต่ต้องป้อน input ที่เรียงมาแล้ว เพราะจับกลุ่มเฉพาะ key ที่เท่ากันและอยู่ติดกันเท่านั้น
// TypeScript / Lodashimport _ from 'lodash';const data = [ { cat: "a", val: 1 }, { cat: "a", val: 2 }, { cat: "b", val: 3 }, { cat: "b", val: 4 },];const grouped = _.groupBy(data, "cat");// { a: [...], b: [...] }import itertools
data = [("a", 1), ("a", 2), ("b", 3), ("b", 4)]# Input ต้องเรียงตาม key ก่อน!for key, group in itertools.groupby(data, key=lambda x: x[0]): items = list(group) print(f"{key}: {items}")# a: [('a', 1), ('a', 2)]# b: [('b', 3), ('b', 4)]functools: higher-order functions
หัวข้อที่มีชื่อว่า “functools: higher-order functions”// TypeScriptconst sum = [1, 2, 3, 4, 5].reduce((acc, x) => acc + x, 0);console.log(sum); // 15import functools
result = functools.reduce(lambda acc, x: acc + x, [1, 2, 3, 4, 5])print(result) # 15
# พร้อม initial valueresult2 = functools.reduce(lambda acc, x: acc + x, [1, 2, 3], 100)print(result2) # 106lru_cache — memoization
หัวข้อที่มีชื่อว่า “lru_cache — memoization”@lru_cache คือ built-in memoization decorator ของ Python ใน TypeScript คู่เทียบคือ Map-based cache แบบ manual หรือ library อย่าง memoize-one
// TypeScript — manual memoizationconst memo = new Map<number, number>();
function fib(n: number): number { if (n < 2) return n; if (memo.has(n)) return memo.get(n)!; const result = fib(n - 1) + fib(n - 2); memo.set(n, result); return result;}
console.log(fib(30)); // 832040import functools
@functools.lru_cache(maxsize=128)def fib(n: int) -> int: if n < 2: return n return fib(n - 1) + fib(n - 2)
print(fib(30)) # 832040print(fib.cache_info()) # hits=28, misses=31, ...partial — เติม arguments ล่วงหน้า
หัวข้อที่มีชื่อว่า “partial — เติม arguments ล่วงหน้า”// TypeScript — bind หรือ arrow wrapperfunction multiply(a: number, b: number): number { return a * b;}
const double = multiply.bind(null, 2);// หรือ: const double = (b: number) => multiply(2, b);
console.log(double(5)); // 10console.log(double(10)); // 20import functools
def multiply(a: int, b: int) -> int: return a * b
double = functools.partial(multiply, 2)print(double(5)) # 10print(double(10)) # 20
# partial ใช้กับ keyword arguments ได้ด้วยdef connect(host: str, port: int, ssl: bool = False) -> str: return f"{'https' if ssl else 'http'}://{host}:{port}"
prod = functools.partial(connect, port=443, ssl=True)print(prod("api.example.com")) # https://api.example.com:443ลองเล่น
หัวข้อที่มีชื่อว่า “ลองเล่น”import itertoolsimport functools
# chainmerged = list(itertools.chain([1, 2], [3, 4], [5]))print("chain:", merged)
# islice from countfirst_six = list(itertools.islice(itertools.count(0, 10), 6))print("count+islice:", first_six)
# groupbywords = ["apple", "ant", "bear", "banana", "cat"]words.sort(key=lambda w: w[0]) # ต้อง sort ก่อน!for letter, group in itertools.groupby(words, key=lambda w: w[0]): print(f" {letter}: {list(group)}")
# lru_cache fibonacci@functools.lru_cache(maxsize=64)def fib(n: int) -> int: if n < 2: return n return fib(n - 1) + fib(n - 2)
print("fib(20):", fib(20))print("cache:", fib.cache_info())
# partialdef power(base: int, exp: int) -> int: return base ** exp
square = functools.partial(power, exp=2)cube = functools.partial(power, exp=3)print("squares:", [square(x) for x in range(1, 6)])print("cubes :", [cube(x) for x in range(1, 6)])Loading Python runtime (first run only)…