“Microsoft PowerToys is a set of utilities for power users to tune and streamline their Windows 10 experience for greater productivity.”
[macOS] MonitorControl
“Control your external monitor brightness, contrast or volume directly from a menulet or with keyboard native keys.”
[JavaScript] Algorithms and Data Structures Projects
These are my notes while doing the course JavaScript Algorithms and Data Structures on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
1. Palindrome Checker
function palindrome(str) {
// clear string
str = str.toLowerCase().replace(/[^a-z0-9]/g, "");
// reverse string
let strBack = str.split("").reverse().join("");
// palindrome?
return (str === strBack) ? true : false;
}
palindrome("_eye");
palindrome("five|\_/|four");
palindrome("1 eye for of 1 eye.");
2. Roman Numeral Converter
function convertToRoman(num) {
const lookup = {M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};
let roman = '';
for ( let i in lookup ) {
while ( num >= lookup[i] ) {
roman += i;
num -= lookup[i];
}
}
return roman;
}
convertToRoman(6);
3. Caesars Cipher
function rot13(str) {
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const length = alphabet.length;
let decode = "";
const getROT13 = index => {
return (index+13 >= length) ? alphabet[13-(length-index)] : alphabet[index+13];
}
for (let i=0; i<str.length; i++) {
let index = alphabet.indexOf(str[i]);
decode += (index<0) ? str[i] : getROT13(index);
}
return decode;
}
rot13("SERR PBQR PNZC")
rot13("SERR CVMMN!")
4. Telephone Number Validator
function telephoneCheck(str) {
let regexCheck = /^(1.*){0,1}(\d{3}|[(]\d{3}[)])[\s|-]*\d{3}.*\d{4}$/g;
let result = regexCheck.test(str);
if (result) {
let length = str.match(/\d/g).length;
result = (length == 7 || length == 10 || (length == 11 && str[0] == 1)) ? true : false;
}
console.log(str.match(regexCheck));
console.log(result);
return result;
}
telephoneCheck("555-555-5555");
telephoneCheck("1 555-555-5555");
telephoneCheck("1 (555) 555-5555");
telephoneCheck("5555555555");
telephoneCheck("555-555-5555")
telephoneCheck("(555)555-5555")
telephoneCheck("1(555)555-5555")
telephoneCheck("1 555)555-5555") //false
telephoneCheck("(6054756961)") //false
telephoneCheck("2 (757) 622-7382") //false
telephoneCheck("10 (757) 622-7382") //false
5. Cash Register
function checkCashRegister(price, cash, cid) {
let changeArr = [];
const currency = { "ONE HUNDRED": 100, "TWENTY": 20, "TEN": 10, "FIVE": 5, "ONE": 1, "QUARTER": 0.25, "DIME": 0.1, "NICKEL": 0.05, "PENNY": 0.01 }
const substract = (a, b) => parseFloat(a - b).toPrecision(4);
const calcAmount = (change, curr) => {
let rest = change % curr;
let div = substract(change, rest) / curr;
return div * curr;
}
let change = substract(cash, price);
//check if cid equals to change
//or if cid is already not enough
let sum = 0;
for (let k=0; k<cid.length;k++) {
sum += cid[k][1]
}
if (sum == change) {
return {status: "CLOSED", change: cid};
} else if (sum < change) {
return {status: "INSUFFICIENT_FUNDS", change: []};
}
//calculate change
for (let i in currency) {
if (change > currency[i]) {
for (let j=0; j<cid.length;j++) {
if (i == cid[j][0]) {
let amount = cid[j][1];
if (substract(change, amount) < 0) {
amount = calcAmount(change, currency[i]);
}
change = substract(change, amount);
changeArr.push([i, amount]);
}
}
}
}
if (change != 0) {
//not able to give the correct change
return {status: "INSUFFICIENT_FUNDS", change: []};
}
return {status: "OPEN", change: changeArr};
}
checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);
checkCashRegister(3.26, 100, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])
checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])
checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])
checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])
[JavaScript] Intermediate Algorithm Scripting
These are my notes while doing the course JavaScript Algorithms and Data Structures on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
1. Sum All Numbers in a Range
function sumAll(arr) {
let num1 = Math.min(arr[0], arr[1]);
let num2 = Math.max(arr[0], arr[1]);
let result = 0;
while (num1 < num2) {
result += num1;
num1++;
}
return result += num2;
}
sumAll([1, 4]);
2. Diff Two Arrays
function diffArray(arr1, arr2) {
var newArr = [];
for (let i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) == -1) {
newArr.push(arr1[i]);
}
}
for (let i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {
newArr.push(arr2[i]);
}
}
return newArr;
}
diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);
3. Seek and Destroy
function destroyer(...arr) {
let newArr = arr.shift();
for (let i = 0; i < arr.length; i++) {
while (newArr.indexOf(arr[i]) > -1) {
newArr.splice(newArr.indexOf(arr[i]), 1);
};
}
return newArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
4. Wherefore art thou
function whatIsInAName(collection, source) {
var arr = [];
var srcKeys = Object.keys(source);
for (let i = 0; i < collection.length; i++) {
let obj = collection[i];
let bool = true;
for (let j = 0; j < srcKeys.length; j++) {
let key = srcKeys[j];
if (!obj.hasOwnProperty(key) || (obj[key] != source[key])) {
bool = false;
}
}
if (bool) {
arr.push(obj);
}
}
return arr;
}
whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", //last: "Capulet" }], { last: "Capulet" });
whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 });
5. Spinal Tap Case
function spinalCase(str) {
let myRegex = /[A-Z][a-z]+|[a-z]+/g;
let arr = str.match(myRegex);
return arr.join("-").toLowerCase();
}
spinalCase('This Is Spinal Tap');
spinalCase("thisIsSpinalTap");
spinalCase("The_Andy_Griffith_Show");
spinalCase("Teletubbies say Eh-oh");
spinalCase("AllThe-small Things");
6. Pig Latin
function translatePigLatin(str) {
let regexAY = /(^[^aeiou]+)/g;
let regexWAY = /(^[aeiou]+)/g;
if (regexAY.test(str)) {
let cutStr = str.match(regexAY);
let newStr = str.substr(cutStr[0].length);
return newStr + cutStr[0] + "ay";
} else if (regexWAY.test(str)) {
return str + "way";
}
}
translatePigLatin("consonant");
translatePigLatin("paragraphs");
translatePigLatin("glove");
translatePigLatin("algorithm");
translatePigLatin("eight");
translatePigLatin("rhythm");
7. Search and Replace
function myReplace(str, before, after) {
if (/^[A-Z]/.test(before)) {
after = after.charAt(0).toUpperCase() + after.slice(1);
} else {
after = after.charAt(0).toLowerCase() + after.slice(1);
}
return str.replace(before, after);
}
myReplace("A quick brown fox jumped over the lazy dog", "jumped", "leaped");
myReplace("Let us go to the store", "store", "mall");
myReplace("He is Sleeping on the couch", "Sleeping", "sitting");
8. DNA Pairing
function pairElement(str) {
let arr = [];
for (let i = 0; i < str.length; i++) {
let tmp = [];
tmp.push(str[i]);
switch(str[i]) {
case "A":
tmp.push("T");
break;
case "T":
tmp.push("A");
break;
case "C":
tmp.push("G");
break;
case "G":
tmp.push("C");
}
arr.push(tmp);
}
return arr;
}
pairElement("GCG");
9. Missing letters
function fearNotLetter(str) {
const alphabet = "abcdefghijklmnopqrstuvwxyz";
let startIndex = alphabet.indexOf(str[0]);
const compareStr = alphabet.slice(startIndex, startIndex + str.length);
for (let i = 0; i < compareStr.length; i++) {
if (compareStr[i] !== str[i]) {
return compareStr[i];
}
}
return undefined;
}
fearNotLetter("abce");
fearNotLetter("bcdf");
fearNotLetter("stvwx");
10. Sorted Union
function uniteUnique(...arr) {
const uniteArray = [].concat(...arr);
let uniteUniqueArray = [];
for (let i = 0; i < uniteArray.length; i++) {
if (uniteUniqueArray.indexOf(uniteArray[i]) == -1) uniteUniqueArray.push(uniteArray[i]);
}
return uniteUniqueArray;
}
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
11. Convert HTML Entities
function convertHTML(str) {
return str
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'")
.replace(/<>/g, "<>");
}
convertHTML("Dolce & Gabbana");
convertHTML("Hamburgers < Pizza < Tacos");
convertHTML("Sixty > twelve");
convertHTML('Stuff in "quotation marks"');
convertHTML("Schindler's List");
convertHTML("<>");
convertHTML("abc");
12. Sum All Odd Fibonacci Numbers
function sumFibs(num) {
let fibo = [1, 1];
const nextNum = fibu => fibo[fibo.length - 1] + fibo[fibo.length - 2];
while (nextNum(fibo) <= num) {
fibo.push(nextNum(fibo));
};
return fibo
.filter(currentNum => currentNum%2 != 0) //odd
.reduce((sum, currentNum) => sum + currentNum, 0);
}
sumFibs(1);
sumFibs(4);
sumFibs(1000)
sumFibs(4000000);
13. Sum All Primes
function sumPrimes(num) {
let primArr = [];
const isPrime = num => { for(let i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
for (let i = 0; i <= num; i++) {
if(isPrime(i)) primArr.push(i);
}
return primArr.reduce((sum, currentNum) => sum + currentNum, 0);
}
sumPrimes(10);
sumPrimes(977);
14. Smallest Common Multiple
function smallestCommons(arr) {
let rangeArr = [...arr];
for (let i = Math.min(...arr) + 1; i < Math.max(...arr); i++) {
rangeArr.push(i);
}
rangeArr.sort((a, b) => b-a);
let lar = rangeArr[0];
let scm = lar;
let bool = false;
while(!bool){
bool = true;
for (let i = 0; i < rangeArr.length; i++) {
if (scm % rangeArr[i] != 0) bool = false;
}
if (bool) return scm;
scm += lar;
}
}
smallestCommons([1,5]);
15. Drop it
function dropElements(arr, func) {
let copy = [...arr];
for (let i = 0; i < arr.length; i++) {
if (func(arr[i])) {
break;
}
copy.shift();
}
return copy;
}
dropElements([1, 2, 3], function(n) {return n < 3; });
16. Steamroller (Recursion)
function steamrollArray(arr) {
var flatArr = [];
const flatten = arr => {
for (let i = 0; i < arr.length; i++){
(Array.isArray(arr[i])) ? flatten(arr[i]) : flatArr.push(arr[i]);
}
return flatArr;
}
return flatten(arr);
}
console.log(steamrollArray([1, [2], [3, [[4]]]]));
17. Binary Agents
function binaryAgent(binary) {
return binary.split(' ') //Split string in array of binary chars
.map(bin => String.fromCharCode(parseInt(bin, 2))) //Map every binary char to real char
.join(''); //Join the array back to a string
}
binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");
18. Everything Be True
function truthCheck(collection, pre) {
return collection.every(col => col.hasOwnProperty(pre) && Boolean(col[pre]));
}
truthCheck([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}, {"user": "Laa-Laa", "sex": "female"}, {"user": "Po", "sex": "female"}], "sex");
19. Arguments Optionalf (was really tough… this is the sample solution)
function addTogether(first, second) {
if (typeof first !== "number") {
return undefined;
}
const sum = second =>
typeof second === "number" ? first + second : undefined;
return typeof second === "undefined" ? second => sum(second) : sum(second);
}
addTogether(2,3);
addTogether("http://bit.ly/IqT6zt");
addTogether(2, "3");
console.log(addTogether(2)([3]));
20. Make a Person
var Person = function(firstAndLast) {
var _arr = firstAndLast.split(" ");
// getter
this.getFirstName = () => _arr[0];
this.getLastName = () => _arr[1];
this.getFullName = () => _arr.join(" ");
// setter
this.setFirstName = first => _arr[0] = first;
this.setLastName = last => _arr[1] = last;
this.setFullName = firstAndLast => _arr = firstAndLast.split(" ");
};
var bob = new Person('Bob Ross');
bob.getFullName();
21. Map the Debris
function orbitalPeriod(arr) {
var GM = 398600.4418;
var earthRadius = 6367.4447;
for(let i in arr){
arr[i].orbitalPeriod = Math.round((2*Math.PI)*Math.sqrt(Math.pow((earthRadius+arr[i].avgAlt),3)/GM));
delete arr[i].avgAlt;
}
return arr;
}
orbitalPeriod([{name : "sputnik", avgAlt : 35873.5553}]);
orbitalPeriod([{name: "iss", avgAlt: 413.6}, {name: "hubble", avgAlt: 556.7}, {name: "moon", avgAlt: 378632.553}])
[JavaScript] Functional Programming
These are my notes while doing the course JavaScript Algorithms and Data Structures on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
Functional programming follows a few core principles:
- Functions are independent from the state of the program or global variables. They only depend on the arguments passed into them to make a calculation
- Functions try to limit any changes to the state of the program and avoid changes to the global objects holding data
- Functions have minimal side effects in the program
Callbacks are the functions that are slipped or passed into another function to decide the invocation of that function. You may have seen them passed to other methods, for example in filter
, the callback function tells JavaScript the criteria for how to filter an array.
Functions that can be assigned to a variable, passed into another function, or returned from another function just like any other normal value, are called first class functions. In JavaScript, all functions are first class functions.
The functions that take a function as an argument, or return a function as a return value are called higher order functions.
When the functions are passed in to another function or returned from another function, then those functions which gets passed in or returned can be called a lambda.
Pass Arguments to Avoid External Dependence in a Function
Example: Adding/Removing a book to/from a bookList without changing the global bookList array. Instead it returns a new array.
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
/* This function should add a book to the list and return the list */
function add(list, bookName) {
return [...list, bookName];
}
/* This function should remove a book from the list and return the list */
function remove(list, bookName) {
return list.filter(book => book !== bookName);
}
var newBookList = add(bookList, 'A Brief History of Time');
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
console.log(bookList); // still contains the same books
The remove function could also look like this:
function remove(arr, bookName) {
let newArr = [...arr];
if (newArr.indexOf(bookName) >= 0) {
newArr.splice(newArr.indexOf(bookName), 1);
return newArr;
}
}
The methods map()
, filter()
, slice()
, concat()
and reduce()
are pure functions, as their output depends solely on its inputs and does not mutate the original array.
map() iterates over each item in an array and returns a new array containing the results of calling the callback function on each element. It does this without mutating the original array.
When the callback is used, it is passed three arguments. The first argument is the current element being processed. The second is the index of that element and the third is the array upon which the map method was called.
const users = [
{ name: 'John', age: 34 },
{ name: 'Amy', age: 20 },
{ name: 'camperCat', age: 10 }
];
const names = users.map(user => user.name); // [ 'John', 'Amy', 'camperCat' ]
A map() implementation could look like this:
var s = [23, 65, 98, 5]; // global Array
Array.prototype.myMap = function(callback) {
var newArray = [];
for (let i = 0; i < this.length; i++) {
newArray.push(callback(this[i]));
}
return newArray;
};
var new_s = s.myMap(function(item) {
return item * 2;
});
filter() calls a function on each element of an array and returns a new array containing only the elements for which that function returns true.
The callback function accepts three arguments. The first argument is the current element being processed. The second is the index of that element and the third is the array upon which the filter method was called.
const users = [
{ name: 'John', age: 34 },
{ name: 'Amy', age: 20 },
{ name: 'camperCat', age: 10 }
];
const usersUnder30 = users.filter(user => user.age < 30); // [ { name: 'Amy', age: 20 }, { name: 'camperCat', age: 10 } ]
A filter() implementation could look like this:
var s = [23, 65, 98, 5]; // global Array
Array.prototype.myFilter = function(callback) {
var newArray = [];
for (let i = 0; i < this.length; i++) {
if (callback(this[i])) {
newArray.push(this[i]);
}
}
return newArray;
};
var new_s = s.myFilter(function(item) {
return item % 2 === 1;
});
slice() returns a copy of certain elements of an array.
var arr = ["Cat", "Dog", "Tiger", "Zebra"];
var newArray = arr.slice(1, 3); // ["Dog", "Tiger"]
concat() combines arrays into a new one without mutating the original arrays.
[1, 2, 3].concat([4, 5, 6]); // Returns a new array [1, 2, 3, 4, 5, 6]
reduce() iterates over each item in an array and returns a single value (i.e. string, number, object, array) via a callback function that is called on each iteration.
const users = [
{ name: 'John', age: 34 },
{ name: 'Amy', age: 20 },
{ name: 'Max', age: 10 }
];
const usersObj = users.reduce((obj, user) => {
obj[user.name] = user.age;
return obj;
}, {});
console.log(usersObj); // { John: 34, Amy: 20, Max: 10 }
[JavaScript] Object Oriented Programming
These are my notes while doing the course JavaScript Algorithms and Data Structures on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
Objects have properties and methods.
let dog = {
name: "Spot",
numLegs: 4,
sayLegs: function() {return `This dog has ${this.numLegs} legs.`;}
};
dog.sayLegs();
Object Constructor Function
//constructor function
function Dog(name, color) {
this.name = name;
this.color = color;
this.numLegs = 4;
}
let myDog = new Dog("Max", "Brown");
myDog instanceof Dog; // true
- Constructors are defined with a capitalized name to distinguish them from other functions that are not
constructors
. - Constructors use the keyword
this
to set properties of the object they will create. Inside the constructor,this
refers to the new object it will create. - Constructors define properties and behaviors instead of returning a value as other functions might.
Get Objects Own Properties
let ownProps = [];
for (let property in myDog) {
if (myDog.hasOwnProperty(property)) ownProps.push(property);
}
console.log(ownProps); // returns [ "name", "color", "numLegs" ]
Prototype Properties to Reduce Duplicate Code
If all instances of an object have the same value for a property, define a prototype to share this property among all instances.
function Dog(name) {
this.name = name; //own property
}
// To add a sinlgle protoype property
Dog.prototype.numLegs = 4; // prototype property
// To add a few at once
Dog.prototype = {
constructor: Dog;
numLegs: 4,
sayName: function() {
console.log("My name is " + this.name);
}
}
Note: There are two kinds of properties: own
properties and prototype
properties!
let myDog = new Dog("Max");
let ownProps = [];
let prototypeProps = [];
for (let property in myDog) {
if (myDog.hasOwnProperty(property)) {
ownProps.push(property);
} else {
prototypeProps.push(property);
};
}
console.log(ownProps); // returns [ "name" ]
console.log(prototypeProps); // returns ["numLegs"]
Note: The hasOwnProperty
method is defined in Object.prototype
, which can be accessed by Dog.prototype
, which can then be accessed by myDog
. This is an example of the prototype
chain.
Constructor Property
Note that the constructor
property is a reference to the constructor function that created the instance. The advantage of the constructor
property is that it’s possible to check for this property to find out what kind of object it is.
console.log(myDog.constructor === Dog); //prints true
It’s generally better to use the instanceof
method to check the type of an object.
Inherit Behaviors from a Supertype
function Animal() { }
Animal.prototype = {
constructor: Animal,
eat: function() {
console.log("nom nom nom");
}
};
function Dog() { }
// Set the prototype of Dog to be an instance of Aninmal
Dog.prototype = Object.create(Animal.prototype);
// Set the constructor to Dog, else it would be function Animal(){...}
Dog.prototype.constructor = Dog;
// A method only the Dog needs
Dog.prototype.bark = function() {
console.log("Woof!");
};
let myDog = new Dog();
myDog.eat();
myDog.bark();
// To override an inherited method, just use the same method name as the one to override
Dog.prototype.eat = function() {
console.log("yami yami yami");
};
myDog.eat(); // returns yami yami yami
This is how JavaScript looks for the method:
- myDog => Is eat() defined here? No.
- Dog => Is eat() defined here? => Yes. Execute it and stop searching.
- Animal => eat() is also defined, but JavaScript stopped searching before reaching this level.
- Object => JavaScript stopped searching before reaching this level.
Mixin to Add Common Behavior Between Unrelated Objects
Inheritance does not work well for unrelated objects like Bird
and Boat
. They can both glide, but a Bird
is not a type of Boat
and vice versa.
For unrelated objects, it’s better to use mixins. A mixin allows other objects to use a collection of functions.
let bird = {
name: "Ducky",
numLegs: 2
};
let boat = {
name: "Titanic",
type: "CruiseShip"
};
let glideMixin = function(obj) {
obj.glide = function() {
console.log("Able to glide!");
}
}
// Adds the method glide to both objects
glideMixin(bird);
glideMixin(boat);
bird.glide();
boat.glide();
Private Properties (Closure)
function Bird() {
let weight = 15; // private variable
this.getWeight = function() {
return weight;
};
}
let ducky = new Bird();
ducky.getWeight(); // returns 15
Immediately Invoked Function Expression (IIFE)
// function declaration and function call
function makeNest() {
console.log("A cozy nest is ready");
}
makeNest();
//IIFE
(function () {
console.log("A cozy nest is ready");
})();
Note that the function has no name and is not stored in a variable. The two parentheses () at the end of the function expression cause it to be immediately executed or invoked.
Use an IIFE to Create a Module
let myModule = (function () {
return {
isCuteMixin: function (obj) {
obj.isCute = function () {
return true;
};
},
singMixin: function (obj) {
obj.sing = function () {
console.log("Singing to an awesome tune");
};
}
}
})();
myModule.singMixin(myDog);
myDog.sing(); // return Singing to an awesome tune
[JavaScript] Objects
These are my notes while doing the course JavaScript Algorithms and Data Structures on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
Objects are similar to arrays
, except that instead of using indexes to access and modify their data, you access the data in objects through what are called properties
. Objects are useful for storing data in a structured way, and can represent real world objects.
var myDog = {
"name": "Dog",
"legs": 4,
"tails": 1,
"friends": ["Max", "Matilda"]
};
Note: If your object has any non-string properties, JavaScript will automatically typecast them as strings.
There are two ways to access the properties of an object: dot notation (.
) and bracket notation ([]
), similar to an array.
var myObj = {
prop1: "val1",
prop2: "val2"
};
var prop1Dot = myObj.prop1; // val1
var prop2Dot = myObj.prop2; // val2
var prop1Bracket = myObj["prop1"]; // val1
var prop2Bracket = myObj["prop2"]; // val2
Append / Delete Properties with dot or bracket notation.
var myObj = {
prop1: "val1",
prop2: "val2"
};
ourDog.prop3 = "val3";
ourDog["prop4"] = "val4";
delete myObj.prop3;
delete myObj["prop4"];
Note: Bracket notation is required if your property has a space in it or if you want to use a variable to name the property.
Check if the property of a given object exists or not using the hasOwnProperty()
method or the in
keyword.
var myObj = {
prop1: "val1",
prop2: "val2"
};
myObj.hasOwnProperty("prop1"); // true
myObj.hasOwnProperty("prop3"); // false
'prob1' in myObj; // true
'prob3' in myObj; // false
JSON – an array of objects https://www.json.org/json-en.html
var myObj = [{
prop1: "val1",
prop2: "val2"
},
{
prop1: "val1",
prop2: "val2"
}];
console.log(JSON.stringify(myObj));
Generate an Array of All Object Keys
Using the Object.keys()
method and passing in an object as the argument will return an array with strings representing each property in the object.
let users = {
Max: {
age: 27
},
Mira: {
age: 32
},
Rich: {
age: 48
}
};
function getArrayOfUsers(obj) {
return Object.keys(obj);
}
getArrayOfUsers(users); // [ 'Max', 'Mira', 'Rich' ]
Note: Also have look at ES6 which includes new object syntax for constructors, getters and setters etc.
[JavaScript] Regular Expressions (regex)
These are my notes while doing the course JavaScript Algorithms and Data Structures on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
Test Method
let myString = "Hello, World!";
let myRegex = /Hello/;
let result = myRegex.test(myString);
Match Literal Strings
Search for multiple patterns.
let petString = "Max has a pet cat.";
let petRegex = /dog|cat|bird|fish/;
let result = petRegex.test(petString);
Ignore Case While Matching using the i
flag.
let petString = "Max has a pet cat.";
let petRegex = /max/i;
let result = petRegex.test(petString); //result true
Extract Matches
"Hello, World!".match(/Hello/);
Note: The .match
syntax is the “opposite” of the .test
method.
Find More Than the First Match
Using the g
flag.
let testStr = "Repeat, Repeat, Repeat";
let repeatRegex = /Repeat/g;
testStr.match(repeatRegex); // Returns ["Repeat", "Repeat", "Repeat"]
Note: You can have multiple flags on your regex like /search/gi
Match Anything with Wildcard Period
The wildcard character: .
let exampleStr = "Let's have fun with regular expressions!";
let unRegex = /.un/;
let result = unRegex.test(exampleStr);
Match Single Character with Multiple Possibilities
let bigStr = "big";
let bagStr = "bag";
let bugStr = "bug";
let bogStr = "bog";
let bgRegex = /b[aiu]g/;
bigStr.match(bgRegex); // Returns ["big"]
bagStr.match(bgRegex); // Returns ["bag"]
bugStr.match(bgRegex); // Returns ["bug"]
bogStr.match(bgRegex); // Returns null
Inside a character set, you can define a range of characters to match using a hyphen character: -
, i.e. to match lowercase letters a
through e
you would use [a-e]
or to match any number through 0 to 5 use [0-5]
.
To create a negated character set, you place a caret character (^
) after the opening bracket and before the characters you do not want to match. For example, /[^aeiou]/gi
Outside of a character set, the caret is used to search for patterns at the beginning of strings. /^firstWord/
.
You can search the end of strings using the dollar sign character $
at the end of the regex. /lastWord$/
Match Characters that Occur Zero|One or More Times
Match a character (or group of characters) that appears:
– one or more times in a row using the +
character. For example, /a+/g
would find a match in "aabc"
and return ["aa"]
.
– zero or more times in a row using the *
character. For example, /go*/g
would find a match in "gooooooal"
and return ["
, but only return goooooo
"]["
in g
"]"guuuuuuual"
.
Find Characters with Lazy Matching
Finds the smallest possible part of the string that satisfies the regex pattern with ?
. For example "titanic"
matched against the adjusted regex of /t[a-z]*?i/
returns ["ti"]
.
Match All Letters and Numbers
The shortcut \w
is equal to [A-Za-z0-9_]
. This character class matches upper and lowercase letters plus numbers. Note, this character class also includes the underscore character (_
).
let quoteSample = "The five boxing wizards jump quickly.";
let alphabetRegexV2 = /\w/g;
let result = quoteSample.match(alphabetRegexV2).length; // result 31
You can search for the opposite of the \w
with \W
. This shortcut is the same as [^A-Za-z0-9_]
.
Match All Numbers
The shortcut to look for digit characters is \d
, with a lowercase d
. This is equal to the character class [0-9]
, which looks for a single character of any number between zero and nine.
The shortcut to look for non-digit characters is \D
. This is equal to the character class [^0-9]
.
Exercise: Restrict Possible Usernames
You need to check all the usernames in a database. Here are some simple rules that users have to follow when creating their username.
- Usernames can only use alpha-numeric characters.
- The only numbers in the username have to be at the end. There can be zero or more of them at the end. Username cannot start with the number.
- Username letters can be lowercase and uppercase.
- Usernames have to be at least two characters long. A two-character username can only use alphabet letters as characters.
let username = "JackOfAllTrades";
let userCheck = /^[a-z][a-z]+\d*$|^[a-z]\d\d$/i;
let result = userCheck.test(username);
Match Whitespace
You can search for whitespace using \s
. Will also match return, tab, form feed, and new line characters. Similar to [ \r\t\f\n\v]
.
let whiteSpace = "Whitespace. Whitespace everywhere!"
let spaceRegex = /\s/g;
whiteSpace.match(spaceRegex); // Returns [" ", " "]
Search for non-whitespace using \S
, Similar to the character class [^ \r\t\f\n\v]
Quantity Specifiers
Quantity specifiers are used with curly brackets ({
and }
). You put two numbers between the curly brackets – for the lower and upper number of patterns.
For example, to match only the letter a
appearing between 3
and 5
times in the string "aaaah"
, your regex would be /a{3,5}h/
.
To only specify the lower number of patterns, keep the first number followed by a comma. /a{3,}h/
To specify a certain number of patterns, just have that one number between the curly brackets. /ha{3}h/
Check for All or None
You can specify the possible existence of an element with a question mark ?
let american = "color";
let british = "colour";
let rainbowRegex= /colou?r/;
rainbowRegex.test(american); // Returns true
rainbowRegex.test(british); // Returns true
Positive and Negative Lookahead
Lookaheads are patterns that tell JavaScript to look-ahead in your string to check for patterns further along.
A positive lookahead will look to make sure the element in the search pattern is there, but won’t actually match it. A positive lookahead is used as (?=...)
A negative lookahead will look to make sure the element in the search pattern is not there. A negative lookahead is used as (?!...)
A practical use of lookaheads is to check two or more patterns in one string. Here is a (naively) simple password checker that looks for between 3 and 6 characters and at least one number:
let password = "abc123";
let checkPass = /(?=\w{3,6})(?=\D*\d)/;
checkPass.test(password); // Returns true
Reuse Patterns Using Capture Groups
You can search for repeat substrings using capture groups. Parentheses, (
and )
, are used to find repeat substrings. To specify where that repeat string will appear, you use a backslash (\
) and then a number. This number starts at 1 and increases with each additional capture group you use.
let repeatStr = "regex regex";
let repeatRegex = /(\w+)\s\1/;
repeatRegex.test(repeatStr); // Returns true
repeatStr.match(repeatRegex); // Returns ["regex regex", "regex"]
Note: Using the .match()
method on a string will return an array with the string it matches, along with its capture group.
Use Capture Groups to Search and Replace
Search and replace text in a string using .replace()
on a string. The inputs for .replace()
is first the regex pattern you want to search for. The second parameter is the string to replace the match or a function to do something.
let str = "one two three";
let fixRegex = /(\w+)\s(\w+)\s(\w+)/;
let replaceText = "$3 $2 $1";
let result = str.replace(fixRegex, replaceText); //result "three two one"
Exercise: Remove Whitespace from Start and End
/* my solution -> selecting the String */
let hello = " Hello, World! ";
let wsRegex = /(\s+)(\w+,\s\w+!)(\s+)/i;
let result = hello.replace(wsRegex, "$2");
/* sample solution -> selecting the Whitespace */
let hello = " Hello, World! ";
let wsRegex = /^\s+|\s+$/g;
let result = hello.replace(wsRegex, "");
[RaspberryPi] Personal Audio Server
RuneAudio | https://www.runeaudio.com/ |
Volumio | https://volumio.org/ |
Mopidy | https://mopidy.com/ |
HiFiBerryOS | https://www.hifiberry.com/hifiberryos/ |
Raspberry Pi Audio Receiver | https://github.com/nicokaiser/rpi-audio-receiver |
Raspbian Stretch as a headless Bluetooth A2DP audio sink | https://gist.github.com/mill1000/74c7473ee3b4a5b13f6325e9994ff84c |
BT-Speaker | https://github.com/lukasjapan/bt-speaker |
Navidrome | https://www.navidrome.org/ (DSub) |
Ampache | https://ampache.org/ |
MPD | https://musicpd.org/ |
myMPD | https://github.com/jcorporation/myMPD |
Funkwhale | https://funkwhale.audio/ |
Multi-room Audio
MoOde | https://moodeaudio.org/ |
Snapcast | https://github.com/badaix/snapcast |
Strobe Audio | https://strobe.audio/ |
[JavaScript] ES6
These are my notes while doing the course JavaScript Algorithms and Data Structures on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
let
and const
Variables with the var
keyword can be overwritten without an error. With E6 the keyword let
was introduced to solve this potential issue.
var camper = 'James';
var camper = 'David'; //no error
let camper = 'James';
let camper = 'David'; // throws an error
"use strict";
x = 3.14; // throws an error because x is not declared
Note: The "use strict"
enables Strict Mode, which catches common coding mistakes and “unsafe” actions.
const
Same features as let
has + read-only.
const FAV_PET = "Cats";
FAV_PET = "Dogs"; // returns error
Note: Use uppercase variable identifiers for immutable values and lowercase or camelCase for mutable values (objects and arrays).
Objects (including arrays and functions) assigned to a variable using const
are still mutable!
Using the const
declaration only prevents reassignment of the variable identifier. You can not use the variable identifier to point to a different array, but the elements are mutable.
const s = [10, 11, 12];
s = [1, 2, 3]; // throws error, trying to assign a const
s[2] = 45; // works just as it would with an array declared with var or let
s.pop(45); //also works fine
Prevent Object Mutation with function Object.freeze
()
Arrow Functions
If you don’t reuse a function you don’t need a name for it, especially when passing a function as an argument to another function.
var magic = function() {
return new Date();
};
/* arrow function syntax */
const magic = () => {
return new Date();
};
/* If there is no function body and only a return, omit the keyword return as well as the backets */
const magic = () => new Date();
Arrow Functions with Parameters
const doubler = (item) => item * 2;
doubler(6); // returns 12
/* If you have a single parameter, omit the parentheses */
const doubler = item => item * 2;
const multiplier = (item, multi) => item * multi;
multiplier(6, 2); // returns 12
Default Parameters
The default parameter is used when the argument is not specified (is undefined).
const hello = (name = "World") => "Hello " + name;
console.log(hello("Mars")); // Hello Mars
console.log(hello()); // Hello World
Rest Parameter
With the rest parameter, you can create functions that take a variable number of arguments. These arguments are stored in an array.
function howMany(...arguments) {
return "You passed " + arguments.length + " arguments.";
}
console.log(howMany(0, 1, 2)); // You passed 3 arguments.
Spread Operator
The spread operator allows us to expand arrays and other expressions in places where multiple parameters or elements are expected. I.e. Math.max()
expects comma-separated arguments, but not an array. The spread operator unpacks all contents of an array into a comma-separated list. To pick specific elements, better use array destructuring.
const array = [2, 99, 7, 4];
/* workaround in ES5 */
var max = Math.max.apply(null, array); // returns 99
/* ES6 */
const max = Math.max(...array); // returns 99
Destructuring Assignment
Destructuring assignment is special syntax for neatly assigning values taken directly from an object,
const person = { name: 'Max', age: 30 };
/* ES5 */
const name = person.name; // name = 'Max'
const age = person.age; // age = 30
/* ES6 */
const { name, age } = person; // name = 'Max', age = 30
// It even allows you to assign a new variable name
const { name: personName, age: personAge } = user; // personName = 'Max', personAge = 30
or from an array.
const [a, b,,, c] = [1, 2, 3, 4, 5, 6, 7];
console.log(a, b, c); // 1, 2, 5
// or collect the rest of the elements into a separate array
const [a, b, ...array] = [1, 2, 3, 4, 5, 7];
console.log(a, b); // 1, 2
console.log(array); // [3, 4, 5, 7]
Destructuring Assignment to Pass an Object as a Function’s Parameters.
const stats = {
max: 56.78,
standard_deviation: 4.34,
median: 34.54,
mode: 23.87,
min: -0.75,
average: 35.85
};
const half = ({max, min}) => (max + min) / 2.0;
Template Literals
Template literal is a special type of string that makes creating complex strings easier.
const person = {
name: "Zodiac Hasbro",
age: 56
};
const greeting = `Hello, my name is ${person.name}!
I am ${person.age} years old.`;
console.log(greeting); // prints
// Hello, my name is Zodiac Hasbro!
// I am 56 years old.
Concise Object Literal Declarations
Short way to define object properties.
const createPerson = (name, age, gender) => {
return {
name: name,
age: age,
gender: gender
};
};
/* Eliminates the redundancy of having to write x: x */
const createPerson = (name, age, gender) => ({
name,
age,
gender
});
Concise Declarative Functions
Remove the function
keyword and colon when defining functions in objects.
/* ES5 function declaration */
const person = {
name: "Max",
sayHello: function() {
return `Hello! My name is ${this.name}.`;
}
};
/* ES6 */
const person = {
name: "Max",
sayHello() {
return `Hello! My name is ${this.name}.`;
}
};
person.sayHello();
class
Syntax to Define a Constructor Function
New syntax to create objects, using the class keyword. The class
syntax replaces the constructor function creation. The new
keyword is used to instantiate an object.
/* ES5 */
var SpaceShuttle = function(targetPlanet){
this.targetPlanet = targetPlanet;
}
var zeus = new SpaceShuttle('Mars');
/* ES6 */
class SpaceShuttle {
constructor(targetPlanet) {
this.targetPlanet = targetPlanet;
}
}
const zeus = new SpaceShuttle('Mars');
Note: The class syntax should not be confused with a full class-based implementation of an object-oriented paradigm.
getters and setters to Control Access to an Object
class Thermostat {
constructor(temperatureFahrenheit) {
this._temperatureCelsius = 5/9 * (temperatureFahrenheit - 32);
}
//getter
get temperature() {
return this._temperatureCelsius;
}
//setter
set temperature(updateTemperatureCelsius) {
this._temperatureCelsius = updateTemperatureCelsius;
}
}
const thermos = new Thermostat(76); // Setting in Fahrenheit scale
let temp = thermos.temperature; // 24.44 in Celsius
thermos.temperature = 26; // use setter
temp = thermos.temperature; // 26 in Celsius
Note: It is convention to precede the name of a private variable with an underscore _
Module Script
A way to easily share code among JavaScript files. Export parts of a file and import the parts you need, where you need them.
You need to create a script in your HTML document with a type of module
.
<script type="module" src="string_functions.js"></script>
const uppercaseString = (string) => string.toUpperCase();
const lowercaseString = (string) => string.toLowerCase();
export {uppercaseString, lowercaseString};
/* import specific functions */
import { uppercaseString, lowercaseString } from './string_functions.js';
uppercaseString("hello");
lowercaseString("WORLD!");
/* import all */
import * as stringFunctions from './string_functions.js';
stringFunctions.uppercaseString("hello");
stringFunctions.lowercaseString("WORLD!");
Promise
Use it to make a promise to do something, usually asynchronously. Promise
is a constructor function, so you need to use the new
keyword to create one. It takes a function, as its argument, with two parameters – resolve
and reject
.
When you make a server request it takes some amount of time, and after it completes you usually want to do something with the response from the server. This can be achieved by using the then
method. The then
method is executed immediately after your promise is fulfilled with resolve
.
const makeServerRequest = new Promise((resolve, reject) => {
// responseFromServer represents a response from a server
let responseFromServer;
if(responseFromServer) {
resolve("We got the data");
} else {
reject("Data not received");
}
});
makeServerRequest.then(result => {
console.log(result);
})
makeServerRequest.catch(error => {
console.log(error);
});