Created
February 17, 2019 21:03
-
-
Save mohamedelshorbagy/cf6612358de68d8dde32fdd4574b1d43 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Question 1 | |
*/ | |
//#region qs1 | |
function groupBy(arr, prop) { | |
return arr.reduce((group, item) => { | |
let value = item[prop]; | |
group[value] = group[value] || []; | |
group[value].push(item); | |
return group; | |
}, {}) | |
} | |
const animalCollective = [ | |
{ type: 'dog', name: 'bobi' }, | |
{ type: 'fish', name: 'glup' }, | |
{ type: 'fish', name: 'glup the second' }, | |
{ type: 'cat', name: 'Aaron' } | |
]; | |
let groupedByType = groupBy(animalCollective, 'type'); | |
console.log(groupedByType); | |
// There's a improvement to this solution using another helper function to groupBy | |
function groupBy(arr, prop) { | |
return arr.reduce((group, item) => { | |
let value = getValue(item, prop); | |
group[value] = group[value] || []; | |
group[value].push(item); | |
return group; | |
}, {}) | |
} | |
/** | |
* | |
* @param { Object } o | |
* @param { String, Array } p // ['type','name'] , 'type.name' , 'type' | |
* @return {*} | |
*/ | |
function getValue(o, p) { | |
let paths = typeof p === "string" ? p.split('.') : p; | |
return paths.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o); | |
} | |
var animalCollective = [ | |
{ | |
type: { | |
name: 'dog', | |
id: 2 | |
}, | |
name: 'bobi' | |
}, | |
{ | |
type: { | |
name: 'fish', id: 3 | |
}, | |
name: 'glup' | |
}, | |
{ | |
type: { | |
name: 'fish', | |
id: 3 | |
} | |
, name: 'glup the second' | |
}, | |
{ | |
type: { | |
name: 'cat', | |
id: 1 | |
}, | |
name: 'Aaron' | |
} | |
]; | |
let groupedByType = groupBy(animalCollective, 'type.name'); | |
console.log(JSON.stringify(groupedByType, null, 2)); | |
//#endregion | |
//#region qs2 | |
/** | |
* Question 2 | |
*/ | |
const arrayOfStrings = ['a', 'b', 'c'].forEach(v => 'a'); | |
arrayOfStrings // undefined | |
// Because the forEach is like for loop it doesn't return an array or return anything it just | |
// loop over the array | |
//#endregion | |
//#region qs3 | |
/** | |
* Question 3 | |
*/ | |
const arrayOfStrings = ['a', 'b', 'c'].map(v => 'a'); | |
arrayOfStrings // ['a','a','a'] | |
// Because the map is returning an array equals to the length of manipulated array | |
// you use fat arrow function which you return implicitly what after the => which here is 'a' | |
//#endregion | |
//#region qs4 | |
/** | |
* Question 4 | |
*/ | |
const ben = { name: 'Ben', age: 2 }; | |
const tom = { name: 'Tom', age: 3 }; | |
const users = [ben, tom]; | |
const userNames = users.map(user => user.name).join(); // 'Ben,Tom' | |
// userNames -> 'Ben,Tom' | |
// ben -> stay the same because you don't mutate the actual data | |
// users.map(user => user.name) ==> you return a new array which have only values in key 'name' | |
// ['Ben','Tom'] | |
// Then you apply join function in the Array bellow which will concatenate them with comma ==> 'Ben,Tom' | |
//#endregion | |
//#region qs5 | |
/** | |
* Question 5 | |
*/ | |
const ben = { name: 'Ben', age: 2 }; | |
const tom = { name: 'Tom', age: 3 }; | |
const users = [ben, tom]; | |
const myNames = users.map(user => { | |
user.name = `My name is ${user.name}`; | |
}).join(); | |
// myNames -> ',' | |
// ben -> stay the same because you don't mutate the actual data | |
// users.map(user => { | |
// user.name = `My name is ${user.name}`; | |
// }) ==> you onlu mutate the user object in the map but you don't return any thing at the end | |
// so it will return a new array equals to the length of the manipulated array | |
// [undefined,undefined] | |
// Then you apply join function in the Array bellow which will concatenate them with comma ==> ',' | |
// because join converts (undefined, null) to empty string | |
//#endregion | |
//#region qs6 | |
/** | |
* Question 6 | |
*/ | |
// * Name 1 advantage and 1 disavantage of using immutable datastructures. | |
// Advantage: - Thread Safety | |
// - Temporal Coupling | |
// - Using Tries like immutable.js | |
// - Structural Sharing | |
// Disadvantages: - It doesn't reuse the memory again like mutation | |
//#endregion | |
//#region qs7 | |
/** | |
* Question 7 | |
*/ | |
import { Subject } from 'rxjs'; | |
import { scan } from 'rxjs/operators'; | |
const actionDispatcher = new Subject(); | |
const state$ = actionDispatcher.asObservable().pipe(scan((currentState, action) => { | |
switch (action.type) { | |
case 'reset': | |
return action.payload | |
case 'add': | |
return action.payload + currentState | |
} | |
throw new Error('Unkown action type'); | |
}, 0)); | |
state$.subscribe(state => console.log(state)); | |
actionDispatcher.next({ type: 'add', payload: 1 }); | |
actionDispatcher.next({ type: 'add', payload: 2 }); | |
actionDispatcher.next({ type: 'reset', payload: 0 }); | |
actionDispatcher.next({ type: 'add', payload: 3 }); | |
// 1 | |
// 3 | |
// 0 | |
// 3 | |
// because here you use scan which is a small state management operator for rxjs which | |
// widely used in many angular or web applications instead of using redux or flux | |
// in every (.next) in actionDispatcher you send a value (or norify) the Subject with new value/action | |
// and you log the response (or new state) in the subscription (.subscribe) of the object | |
//#endregion | |
//#region qs8 | |
/** | |
* Question 8 | |
*/ | |
function groupBy(arr: any[], prop: string) { | |
return arr.reduce((group: {}, item: {}) => { | |
let value: string = item[prop]; | |
group[value] = group[value] || []; | |
group[value].push(item); | |
return group; | |
}, {}) | |
} | |
interface IAnimal { | |
type: string, | |
name: string | |
} | |
const animalCollective: IAnimal[] = [ | |
{ type: 'dog', name: 'bobi' }, | |
{ type: 'fish', name: 'glup' }, | |
{ type: 'fish', name: 'glup the second' }, | |
{ type: 'cat', name: 'Aaron' } | |
]; | |
let groupedByType: any = groupBy(animalCollective, 'type'); | |
console.log(groupedByType); | |
/*************************** */ | |
import { Subject } from 'rxjs'; | |
import { scan } from 'rxjs/operators'; | |
interface IAction { | |
type: string, | |
payload: number | |
} | |
const actionDispatcher: Subject<any> = new Subject(); | |
const state$ = actionDispatcher.asObservable().pipe(scan((currentState: number, action: IAction) => { | |
switch (action.type) { | |
case 'reset': | |
return action.payload | |
case 'add': | |
return action.payload + currentState | |
} | |
throw new Error('Unkown action type'); | |
}, 0)); | |
state$.subscribe(state => console.log(state)); | |
actionDispatcher.next({ type: 'add', payload: 1 }); | |
actionDispatcher.next({ type: 'add', payload: 2 }); | |
actionDispatcher.next({ type: 'reset', payload: 0 }); | |
actionDispatcher.next({ type: 'add', payload: 3 }); | |
//#endregion | |
//#region qs9 | |
/** | |
* Question 9 | |
*/ | |
// * What is the difference between type checking at compiletime and type checking runtime ? | |
// * Compile-Time is to compile the code first to find out these checks which generate compile-time type checks due to | |
// * type mistake for appropriate syntax like Typescript, Flow | |
// * Runtime is checking the correctness of the type while the program is running like Flow-runtime, swift | |
// * | |
// * Which kind of type checking is used by typescript ? | |
// * Compile Time | |
// * there's some proposal to typescript to have some Runtime checks on it to be shipped with the generated source code | |
// * Which kind of type checking is used by javascript ? | |
// * Compile-Time & Runtime | |
//#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment