Exclude items array according excludes array
Implement a function to exclude matching items from all
according to excludes
array.
Assume there are m
items in all
, n
items in excludes
. Below are 3 versions to solve this problem
- Bad version: O(m*n)
- Decent version: O(m*n), but can return early in some case
- Good version: O(max(m, n))
1 | /* |
Create chaining function
Implement a function can take an executor
, onSuccess
, onFail
callbacks, and call them in the right time. For the following example, please finish the exec
function
slow
is executor, defined by userssuccess(onSuccess)
:onSuccess
also defined by users, to receive the successful generated resultfail(onFail)
:onFail
also defined by users, to receive error message
1 |
|
Cache expensive function execution
If a function execution is very expensive, such as encoding function. Cachify the expensive function, so that next time it will instantly return last calculated result, when the same arguments passed in.
Barely Workable Version [ can only cache one function ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34function cachify(fn){
cache = {}
return function(){
let key = [].slice.call(arguments).join(',')
if(cache[key])
return cache[key]
else{
cache[key] = fn.apply(null, arguments)
return cache[key]
}
}
}
// TEST
let timeConsumeFun = function( arg1, arg2 ){
for( let i = 0; i < 100000000; i++ ){
arg1 += 1;
arg2 += 1
}
return arg1 + arg2
}
let startTime = Date.now()
let cachedFun = cachify(timeConsumeFun)
let result1 = cachedFun(0, 0)
let timeUsedFirstTime = Date.now() - startTime
console.log("Result of first call should be 200000000: "+ result1)
console.log("Time used for first call: "+ timeUsedFirstTime)
startTime = Date.now()
let result2 = cachedFun(0, 0)
let timeUsedSecondTime = Date.now() - startTime
console.log("Result of seconde call should be 200000000: "+ result2)
console.log("Time used for second call: "+ timeUsedSecondTime)Good Version I : [Can cache any function with different parameters]
cach all functions and its input/output in only one map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56function cachify(fn) {
try {
cache // must use this var, in any way
console.dir(cache)
} catch (e) {
if (e.name === "ReferenceError")
cache = new Map()
} finally {
return function () {
let params = [].slice.call(arguments).join(',')
if (cache.has(fn)) {
if (cache.get(fn).has(params))
return cache.get(fn).get(params)
else {
let res = fn.apply(null, arguments)
cache.get(fn).set(params, res)
return res
}
} else {
let res = fn.apply(null, arguments)
cache.set(fn, new Map().set(params, res))
return res
}
}
}
}
// TEST
let test1 = function (arg1, arg2) {
for (let i = 0; i < 10000000; i++) {
arg1 += 1;
arg2 += 1
}
return arg1 + arg2
}
let startTime = Date.now()
let cachedFun1 = cachify(test1)
let result11 = cachedFun1(0, 0)
let timeUsedFirstTime = Date.now() - startTime
console.log("Result of first call should be 20000000: " + result11)
console.log("Time used for first call: " + timeUsedFirstTime)
startTime = Date.now()
let result12 = cachedFun1(0, 0)
let timeUsedSecondTime = Date.now() - startTime
console.log("Result of seconde call should be 20000000: " + result12)
console.log("Time used for second call: " + timeUsedSecondTime)
let test2 = (a, b) => a + b
let cachedFun2 = cachify(test2)
let result21 = cachedFun2(0, 0)
console.log(result21)
let result22 = cachedFun2(1, 1)
console.log(result22)Good Version II : [Can cache any function with different parameters]
cache each function and its input/output in separate map, using closure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22function cachify( fn ){
// <fn, <input, output> >
let map = new Map()
return function(...args){
if( map.has(fn) ){
let inOutMap = map.get(fn)
let argsStr = args.join('/')
if( inOutMap.has(argsStr) ){
return inOutMap.get(argsStr)
}
}
let res = fn(...args)
if(!map.has(fn)) {
let inOutMap = new Map()
map.set(fn, inOutMap)
}
map.get(fn).set(args.join('/'), res)
console.log(map)
return res
}
}
Polyfill Array.prototype.forEach
1 | // 1. Example to use forEach() |
Polyfill Array.prototype.reduce
1 | // if(Array.prototype.reduce){ |
Closure: a comparison
- ONLY variable inside a function can form into closure scope
- only variable itself cannot be updated or
1 | // Version 1: `countVal` is a function |
Variable Hoisting
This following code snippet will parsed firstly into next code snippet
1 | bar(); |
The snippet will convert to the following: 上面代码在运行之前将会被转化。JavaScript 将会把 var
表达式和 function
声明提升到当前作用域的顶部。
1 | // var 表达式被移动到这里 |
Type conversion: string to number
Number("10")
: return a primitive numbernew Number("10")
: return a number object1
2
3new Number(10) === 10; // False, 对象与数字的比较
Number(10) === 10; // True, 数字与数字的比较
new Number(10) + 0 === 10; // True, 由于隐式的类型转换
LeetCode: word break
Given an array of strings and a target string, determin whether the target string can be formed using strings from the given array.
BAD version : many duplicate check for substrings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function canFormTarget( arr, target ){
if( target.length === 0 ) return true
for( let i = 0; i < target.length; i++ ){
let prefix = target.substr(0,i+1)
let suffix = target.substr(i+1)
if( arr.includes(prefix) && canFormTarget(arr, suffix) )
return true
}
return false
}
// Test
let arr = ["l", "e", "ee", "et", "co", "d", "e"]
let target = "leetcode"
console.time("test")
let result = canFormTarget(arr, target)
console.timeEnd("test")GOOD version : use DP with memoization to speed up process
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23let strChecked = new Map()
function canFormTarget( arr, target ){
if( target.length === 0 ) return true
if( strChecked.has(target) ) return strChecked.get(target)
for( let i = 0; i < target.length; i++ ){
let prefix = target.substr(0,i+1)
let suffix = target.substr(i+1)
if( arr.includes(prefix) && canFormTarget(arr, suffix) ){
strChecked.set(target, true)
return true
}
}
strChecked.set(target, false)
return false
}
// Test
let arr = ["l", "e", "ee", "et", "co", "d", "e"]
let target = "leetcode"
console.time("test")
let result = canFormTarget(arr, target)
console.timeEnd("test")
Curry Function
Implement a curry function addToBase
will return another function take an argument to be added on the base.
1 | function addToBase(base){ |
Counting frequency of values in an object
1 | var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']; |
Group objects by a certain property
1 | let people = [ |
Function composition enabling piping
1 | const double = x => x + x; |
Another composition / pipe example
1 | const compose = (...args)=>{ |
Composition vs Inheritance
Here we compare 2 ways to make an Employee
object, using Composition and Inheritance
make
employee
using Inheritance1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22function Person(fn, ln){
this.firstName = fn;
this.lastName = ln;
};
Person.prototype.getInfo = function(greetStr){
//In real life this method/function will be bigger
return `${greetStr}, I am ${this.firstName} ${this.lastName}.`
}
function Employee(fn, ln, empid){
Person.call(this, fn, ln);
this.empid = empid;
};
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.getId = function(greetStr){
return return `${greetStr}, my employee id is ${this.empid}.`;
}s
var e1 = new Employee("John", "Doe", 123);
console.log( e1.getInfo('Hi') ); // Hi, I am John Doe.
console.log( e1.getId('Hello') ); // Hello, my employee id is 123.make
employee
using Composition [ Closure applied ]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19function getInfo(firstName, lastName, greetStr){
return `${greetStr}, I am ${firstName} ${lastName}.`
}
function getId(empid, greetStr){
return `${greetStr}, my employee id is ${empid}.`;
}
function createEmployee(fn, ln, empid){
return {
empid: empid,
getId : (greetStr) => getId(empid, greetStr),
getInfo: (greetStr) => getInfo(fn, ln, greetStr)
};
}
var e1 = createEmployee("john", "doe", 123);
console.log( e1.getInfo('Hi') ); // Hi, I am John Doe.
console.log( e1.getId('Hello') ); // Hello, my employee id is 123.
CSS: width:100%
for parent with position:relative
& position:absolute
will escape from normal document flow:
position: absolute
: Note, if notop
,left
,right
,bottom
specified, it will stay at its original positionpostion:fixed
won’t escape from normal document flow:
position: relative
float
width:100%
: the percentage means relative to its parentsIf still in normal document flow: parent is its container
if not in normal document flow: parent is the element it positioned relative to
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<html>
<head>
<style>
#outer{
width: 100px;
height: 100px;
border: 1px red solid;
}
#inner1{
position: relative;
width:100%;
height:100%;
border: 1px green solid;
}
#inner2{
position: absolute;
width:100%;
height:100%;
border: 1px blue solid;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner1">
</div>
<div id="inner2">
</div>
</div>
</body>
</html>
Add, Remove& Toggle Classes With classList
in JavaScript
Say we have an element like this:
1 | <div class="cool new shades"> |
We can get all class names using 2 ways:
element.classList
1
2
3
4
5
6let shadesEl = document.querySelector('.cool');
console.log(shadesEl.classList);
// ["cool", "new", "shades", value: "cool new shades"]
console.log(shadesEl.classList[1]); // newelement.className
1
2
3
4let shadesEl = document.querySelector('.cool');
console.log(shadesEl.className);
// "cool new shades"add
1
2shadesEl.classList.add('make', 'me', 'look', 'rad');
// <div class="cool new shades make me look rad">content </div>contains
1
console.log(shadesEl.classList.contains('look')); // true
item
1
2
3console.log(shadesEl.classList.item(3)); // make
// equals way
console.log(shadesEl.classList[3]); // makeremove
1
2shadesEl.classList.remove('cool', 'make', 'me');
// <div class="new shades look rad">content </div>toggle
1
2
3
4
5
6
7
8
9
10
11// GOOD version
coolButton.addEventListener('click', () => {
shadesEl.classList.toggle('cool');
});
// BAD toggle
if (shadesEl.classList.contains('rad')) {
shadesEl.classList.remove('rad');
} else {
shadesEl.classList.add('rad');
}