Skip to content

Instantly share code, notes, and snippets.

@deepakshrma
Last active October 27, 2022 16:21
Show Gist options
  • Save deepakshrma/78b8a14940b17ffaff159d3188754597 to your computer and use it in GitHub Desktop.
Save deepakshrma/78b8a14940b17ffaff159d3188754597 to your computer and use it in GitHub Desktop.
Functional Programming In JavaScript-TypeScript for Beginners
function calculateInterest(p: number, t: number, r: number) {
return (p * t * r) / 100;
}
console.log(calculateInterest(1000, 5, 5));
//250
def calculateInterest(p: float, t: int, r: float):
return (p * t * r) / 100
print(calculateInterest(1000, 5, 5))
## Output: 250
def twoSum(nums, target):
num_map = {}
for i in range(len(nums)):
if nums[i] in num_map:
return [num_map[nums[i]], i]
else:
num_map[target-nums[i]] = i
print(twoSum([2, 7, 11, 15], 9))
def is_real_number(num):
return type(num) == int or type(num) == float
def divide(num, den):
if not(is_real_number(num) and is_real_number(den)):
raise ValueError("Invalid argument")
if den == 0:
raise ValueError("Number is not divisible by zero")
return num/den
def add(*arg):
if any([not(is_real_number(i)) for i in arg]):
raise ValueError("Invalid argument")
return sum(arg)
print(divide(10, 2)) # 5.0
print(add(1, 2, 3)) # 6
print(divide("10", 2)) # ValueError: Invalid argument
print(divide(10, 0)) # ValueError: Number is not divisible by zero
function trim(str: string) {
return str.replace(/^\s+|\s+$/g, "");
}
console.log(trim(" This text had extra spaces.. "));
// "This text had extra spaces.."
import re
trimReg = re.compile(r"^\s+|\s+$", re.IGNORECASE)
def trim(txt: str):
return re.sub(trimReg, "", txt)
print(trim(" This text had extra spaces.. "))
## "This text had extra spaces.."
def twoSum(nums, target):
num_map = {}
for index, num in enumerate(nums):
if num in num_map:
return [num_map[num], index]
else:
num_map[target-num] = index
def greet(name):
print(f"Welcome Mr/Ms. {name}")
gr_8 = greet
greet("Deepak") # Welcome Mr/Ms. Deepak
gr_8("Deepak") # Welcome Mr/Ms. Deepak
enum GENDER {
MR = "Mr.",
MS = "Miss.",
}
function greeting(name: string, is: GENDER = GENDER.MR) {
return `Hello, ${is == GENDER.MR ? GENDER.MR : GENDER.MS} ${name}`;
}
console.log(greeting("Deepak"));
// "Hello, Mr. Deepak"
import re
trimReg = re.compile(r"^\s+|\s+$", re.IGNORECASE)
trim = lambda txt:re.sub(trimReg, "", txt)
print(trim(" This text had extra spaces.. "))
## "This text had extra spaces.."
nums = [1, 2, 3, 4, 5, 6]
name = "123456"
sslice = slice(1, 6, 2)
print(nums[slice(1, 6)]) # [1, 2, 3, 4, 5, 6]
print(nums[sslice]) # [2, 4, 6]
print(name[sslice]) # 246
def inc(x):
return x + 1
def dec(x):
return x - 1
def operate(func, x):
result = func(x)
return result
operate(inc, 5) # 6
operate(dec, 5) # 4
function rand(num = 4) {
return Math.random().toString(16).substr(-num);
}
function uuid(): string {
return [rand(8), rand(4), rand(4), rand(4), rand(12)].join("-");
}
console.log(uuid());
from enum import Enum
class GENDER(Enum):
MR = "Mr."
MS = "Miss."
def greeting(
name: str, grt: GENDER = GENDER.MR):
return f"Hello, {grt.value} {name}"
print(greeting("Deepak"))
print(greeting("Mina", GENDER.MS))
## "Hello, Mr. Deepak"
nums = [1, 2, 3, 4, 5, 6]
name = "123456"
sslice = slice(1, 6, 2)
print(nums[sslice] == nums[1:6:2]) # True
print(name[sslice] == name[1:6:2]) # True
def decorator():
def inner():
print("Inner function")
return inner
outer = decorator()
outer()
# Inner function
const groupBy = <T = any>(fn: (item: T, i: number) => any, data: T[]) =>
data.map(fn).reduce((acc, val, i) => {
acc[val] = (acc[val] || []).concat(data[i]);
return acc;
}, {});
const { odds, evens } = groupBy((item) => (item % 2 == 0 ? "evens" : "odds"), [
1,
2,
3,
4,
5,
]);
console.log(odds, evens);
// [ 1, 3, 5 ] [ 2, 4 ]
import random
def rand(num=4):
return hex(int(random.random() * 10000000))[-num:]
def uuid() -> str:
return "-".join([rand(8), rand(4), rand(4), rand(4), rand(12)])
print(uuid())
# 0x4484cd-610d-9b87-55bb-0x85b665
class Solution:
def isPalindrome(self, x):
num1 = str(x)
num2 = num1[::-1]
return num1 == num2
print(Solution().isPalindromewithReverse(121)) # True
print(Solution().isPalindromewithReverse(-121)) # False
class Callable:
def __init__(self):
print("An instance of Callable was initialized")
def __call__(self, *args, **kwargs):
print("Arguments are:", args, kwargs)
x = Callable()
print("now calling the instance:")
x(3, 4, x=11, y=10)
"""
An instance of Callable was initialized
now calling the instance:
Arguments are: (3, 4) {'x': 11, 'y': 10}
"""
const PI = 3.141592653589793;
// PI = 1
// Cannot assign to 'PI' because it is a constant.
const numbers = Object.freeze([1, 2, 3, 4]);
// Just like normal array, you can map on values
numbers.forEach((x) => console.log(x));
// numbers.push()
// Cannot add property 4, object is not extensible
// OR in TS, Property 'push' does not exist on type 'readonly number[]
from functools import reduce
def splitBy(fn, arr):
def divider(tpl, item):
if fn(item):
tpl[0].append(item)
else:
tpl[1].append(item)
return tpl
return reduce(divider, arr, ([], []))
nums = [1, 2, 3, 4, 5]
odds, evens = splitBy(lambda item: item % 2 != 0, nums)
print(odds, evens)
# [ 1, 3, 5 ] [ 2, 4 ]
def join(*args):
return reduce(lambda a, b: f"{a}_{b}", args)
def memoize(func):
memo = {}
def helper(*args):
key = join(*args)
if key not in memo:
memo[key] = func(*args)
return memo[key]
return helper
def decorator(func):
def inner():
print("run something before actual function")
func()
print("run something after actual function")
return inner
def func():
print("something...")
decorated_func = decorator(func)
decorated_func()
"""
run something before actual function
something...
run something after actual function
"""
const numbers = Object.freeze([1, 2, 3, 4]);
// Just like normal array, you can loop on values
numbers.forEach((x) => console.log(x));
// Copy array and add new
const anotherNumbers = [...numbers].concat(5);
//[1,2,3,4,5]
thistuple = ("apple", "banana", "cherry")
print(thistuple[0], thistuple[1], thistuple[2])
# apple banana cherry
thisset = {"apple", "banana", "cherry"}
print(thisset)
## {'apple', 'cherry', 'banana'}
thisset.remove("apple")
print(thisset)
## {'banana', 'cherry'}
thisset.add("apple")
print(thisset)
## {'banana', 'cherry'}
thistuple[0] = "ball"
print(thistuple)
# TypeError: 'tuple' object does not support item assignment
@memoize
def powHelper(x, n):
if n == 0:
return 1
return powHelper(x*x, n/2) if n % 2 == 0 else x * powHelper(x*x, (n-1)/2)
class Solution:
def myPow(self, x, n):
m = n
if n < 0:
m *= -1
res = powHelper(x, m)
return res if n >= 0 else 1/res
print(Solution().myPow(2, 3)) # 8
print(Solution().myPow(2, 5)) # 32
print(Solution().myPow(2, -5)) # 0.03125
def decorator(func):
def inner():
print("run something before actual function")
func()
print("run something after actual function")
return inner
@decorator
def func():
print("something...")
func()
"""
run something before actual function
something...
run something after actual function
"""
const configs = {
API_URL: "some random urls",
TIMEOUT: 30 * 60 * 10000, //in ms
};
const newConfigs = {
...configs,
SERVER_TIMEOUT: 100 * 60 * 10000, //in ms
};
// OR
const newConfigs2 = Object.assign({}, newConfigs, {
SERVER_TIMEOUT: 100 * 60 * 10000,
});
nums = [1, 2, 3]
numscopy = nums.copy()
nums.append(4)
print(nums, numscopy)
## [1, 2, 3, 4] [1, 2, 3]
numscopy.append(5)
print(nums, numscopy)
## [1, 2, 3, 4] [1, 2, 3, 5]
numsmerged = nums.copy()
numsmerged.extend(numscopy)
print(numsmerged)
## [1, 2, 3, 4, 1, 2, 3, 5]
# You can add any iterable using extend
# Set
numsmerged.extend({6, 7})
print(numsmerged)
## [1, 2, 3, 4, 1, 2, 3, 5, 6, 7]
## Dictionary- Default is keys
numsmerged.extend({8: "v1", 9: "v2"})
print(numsmerged)
## [1, 2, 3, 4, 1, 2, 3, 5, 6, 7, 8, 9]
# Dictionary Values
numsmerged.extend(({8: "v1", 9: "v2"}).values())
print(numsmerged)
### [1, 2, 3, 4, 1, 2, 3, 5, 6, 7, 8, 9, 'v1', 'v2']
def sum(*args):
res = 0
for num in args:
res += num
return res
print(sum(1, 2, 3)) # 6
print(sum(1, 2, 3, 4, 5)) # 15
def prettify(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
@prettify
def pretty_print(*msg, **kwargs):
print(*msg, **kwargs)
pretty_print("Hello World")
pretty_print(1, 2, 3)
"""
******************************
Hello World
******************************
******************************
1 2 3
******************************
"""
const details = new Map([
["name", "deepak"],
["address", "some where in world"],
]);
for (let key of details.keys()) {
console.log(key);
}
//"name" "address"
const updatedDetails = new Map([
...details.entries(),
["newAddress", "still some where in world"],
]);
for (let key of updatedDetails.keys()) {
console.log(key);
}
//"name" "address" "newAddress"
class Dict(dict):
def __add__(self, other):
copy = self.copy()
copy.update(other)
return copy
def __radd__(self, other):
copy = other.copy()
copy.update(self)
return copy
city_codes = Dict({"IN": 91, "USA": 1, "UK": 2})
print(city_codes)
## {'IN': 91, 'USA': 1, 'UK': 2}
city_codes = city_codes + {"SG": 65}
print(city_codes)
## {'IN': 91, 'USA': 1, 'UK': 2, 'SG': 65}
# Using reduce, simplified version
from functools import reduce
def sum(*args):
return reduce(lambda a, b: a+b, args)
print(sum(1, 2, 3))
print(sum(1, 2, 3, 4, 5))
class RealNumValidator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwds):
if any([not(is_real_number(i)) for i in args]):
raise ValueError("Invalid argument")
return self.func(*args)
class ZeroValidator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwds):
if len(args) < 2 or args[1] == 0:
raise ValueError("Number is not divisible by zero")
return self.func(*args)
const split = (token = /\s+/, str = "") => str.split(token);
const splitByHash = (str: string) => split(/#/, str);
console.log(splitByHash("This#is#awesome"));
// [ 'This', 'is', 'awesome' ]
def split(token=" ", txt=""):
return txt.split(token)
def curry(func):
# to keep the name of the curried function:
curry.__curried_func_name__ = func.__name__
f_args, f_kwargs = [], {}
def f(*args, **kwargs):
nonlocal f_args, f_kwargs
if args or kwargs:
f_args += args
f_kwargs.update(kwargs)
return f
else:
result = func(*f_args, *f_kwargs)
f_args, f_kwargs = [], {}
return result
return f
splitByHash = curry(split)("#")
print(splitByHash("This#is#awesome#curry")())
### ['This', 'is', 'awesome', 'curry']
def range(**args):
start = args["start"] if "start" in args else 0
end = args["end"] if "end" in args else 100
res = []
while start < end:
res.append(start)
start = start+1
return res
print(range(start=10, end=20)) # [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
class RealNumValidator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwds):
if any([not(is_real_number(i)) for i in args]):
raise ValueError("Invalid argument")
return self.func(*args)
class ZeroValidator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwds):
if len(args) < 2 or args[1] == 0:
raise ValueError("Number is not divisible by zero")
return self.func(*args)
def is_real_number(num):
return type(num) == int or type(num) == float
@RealNumValidator
@ZeroValidator
def divide(num, den):
return num/den
@RealNumValidator
def add(*arg):
return sum(arg)
print(divide(10, 2)) # 5.0
print(add(1, 2, 3)) # 6
print(divide("10", 2)) # ValueError: Invalid argument
print(divide(10, 0)) # ValueError: Number is not divisible by zero
// Helper method, Curries a function.
// https://decipher.dev/30-seconds-of-typescript/docs/curry
const curry = (fn: Function, arity = fn.length, ...args: any[]): any =>
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
const split = (token = /\s+/, str = "") => str.split(token);
const splitByHash = curry(split, 2)("#");
console.log(splitByHash("This#is#awesome"));
// [ 'This', 'is', 'awesome' ]
def interest(p, t, r):
return (p*t*r)/100
print(interest(100, 5, 1))
# 5.0
def is_loan_approved(loan_interest):
return "REJECTED" if loan_interest > 100 else "PASS"
print(is_loan_approved(interest(1000, 5, 1))) # PASS
print(is_loan_approved(interest(10000, 5, 1))) # REJECTED
## Using compose
def compose(g, f):
def h(*arg):
return g(f(*arg))
return h
is_loan_valid = compose(is_loan_approved, interest)
print(is_loan_valid(100, 5, 1)) ## PASS
print(is_loan_valid(10000, 5, 1)) ## REJECTED
numbers = [1, 2, 3, 4, 5]
result = map(lambda x: x*x, numbers) # return map object
print(list(result)) # need to convert to list
# Output: [1, 4, 9, 16, 25]
// Helper method, Performs right-to-left function composition.
// https://decipher.dev/30-seconds-of-typescript/docs/compose/
const compose = (...fns: Function[]) =>
fns.reduce((f, g) => (...args: any[]) => f(...[g(...args)]));
const add10 = (x: number) => x + 10;
const multiply = (x: number, y: number) => x * y;
const multiplyAndAdd5 = compose(add10, multiply);
console.log(multiplyAndAdd5(5, 2)); // 20
import json
from urllib.request import urlopen
def requestJson(url, default=[]):
data = default
try:
data = json.load(urlopen(url))
except:
print("Error while fetching data...")
return data
todos_url = "https://jsonplaceholder.typicode.com/todos"
def main():
# Request todos json data
todos = requestJson(todos_url)
print(todos[0])
## {'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
completed_todos = list(filter(lambda todo: todo["completed"], todos))
print(completed_todos[0])
## {'userId': 1, 'id': 4, 'title': 'et porro tempora', 'completed': True}
# fetch user ids who completed todos
user_ids = set(map(lambda todo: todo["userId"], completed_todos))
print(user_ids)
## {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
# Get all user information
users = list(map(lambda id: requestJson(
f"https://jsonplaceholder.typicode.com/users/{id}"), user_ids))
print(users[0])
## {'id': 1, 'name': 'Leanne Graham', ...}
if __name__ == "__main__":
main()
numbers = [1, 2, 3, 4, 5]
def mapInt(num):
return num*num if num % 2 == 0 else num*num*num
print(list(map(mapInt, numbers)))
const sum = (nums: number[]) => nums.reduce((s, i) => s + i, 0)
const average = (nums: number[]) => sum(nums) / nums.length
const getActiveUserAges = (data: UserType[] = []) => data.filter(user => user.active === true).map(u => u.age)
const users = [
{
name: "deepak",
age: 31,
active: true
},
{
name: "sandy",
age: 20,
active: false
},
{
name: "unknown",
age: 35,
active: true
}
]
type UserType = typeof users[0]
const activeUsers = getActiveUserAges(users)
const sumOfAges = sum(activeUsers)
console.log(sumOfAges/ activeUsers.length)
import json
from urllib.request import urlopen
def curry(func):
# to keep the name of the curried function:
curry.__curried_func_name__ = func.__name__
f_args, f_kwargs = [], {}
def f(*args, **kwargs):
nonlocal f_args, f_kwargs
if args or kwargs:
f_args += args
f_kwargs.update(kwargs)
return f
else:
result = func(*f_args, *f_kwargs)
f_args, f_kwargs = [], {}
return result
return f
def neg(fn):
def _neg(*arg):
return not fn(*arg)
return _neg
prop = curry(lambda key, data: data[key])
def isCompleted(todo): return todo["completed"]
isNotCompleted = neg(isCompleted)
getId = prop("id")
## Rest of the code
def main():
todos = requestJson(todos_url)
userWhoCompletedTodos = list(map(getId, filter(isCompleted, todos)))
usersWhoNotCompletedIds = list(map(getId, filter(isNotCompleted, todos)))
print(len(userWhoCompletedTodos), len(usersWhoNotCompletedIds))
if __name__ == "__main__":
main()
// helper method
const compose = (...fns: Function[]) =>
fns.reduce((f, g) => (...args: any[]) => f(...[g(...args)]));
// sum of ages
const getSumAges = compose(sum, getActiveUserAges);
console.log(getSumAges(users));
// average of ages
const getAverageOfAges = compose(average, getActiveUserAges);
console.log(getAverageOfAges(users));
async function main() {
const response = await fetch("https://jsonplaceholder.typicode.com/todos/") // fetch todos
.then((r) => r.json()); // then extract json
// Response Todo[]
// Todo {userId: number, id: number, title: string, completed: boolean}
const todos = response; // extract Todo values
console.log(todos[0]); // [{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}, ...]
const completedTodos = todos.filter((todo) => todo.completed);
const usersIds = completedTodos.map((todo) => todo.userId);
const getAllUserById = (id) =>
fetch(`https://jsonplaceholder.typicode.com/users/${id}`).then((r) =>
r.json()
);
const userWhoCompletedTods = await Promise.all(usersIds.map(getAllUserById));
console.log(userWhoCompletedTods.length);
console.log(userWhoCompletedTods[0]);
}
main();
const curry = (fn, arity = fn.length, ...args) =>
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
const filter = (fn, data) => data.filter(fn);
const map = (fn, data) => data.map(fn);
const not = (fn) => (...args) => !fn(...args);
const prop = curry((key, data) => data[key]);
const isCompleted = (item) => item.completed;
const isNotCompleted = not(isCompleted);
const getId = prop("id");
const userWhoCompletedTodos = map(getId, filter(isCompleted, todos));
const usersWhoNotCompletedIds = map(getId, filter(isNotCompleted, todos));
console.log(userWhoCompletedTodos.length, usersWhoNotCompletedIds.length);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment