万丈高楼平地起,打好基础最要紧。
原网站地址:https://learn.freecodecamp.one/
代码是码出来的,各位多多练习。
1. 将摄氏温度转换成华氏温度
将摄氏度转换为华氏度的算法为:摄氏度 ×
9/5 + 32
function convertToF(celsius) {
let fahrenheit = celsius * 9 / 5 + 32;
return fahrenheit;
}
convertToF(30);
2. 翻转字符串
反转给出的字符串。
function reverseString(str) {
return str = str.split('').reverse().join('');
}
reverseString("hello");
function reverseString(str) {
for (var reversedStr = "", i = str.length - 1; i >= 0; i--) {
reversedStr += str[i];
}
return reversedStr;
}
3. 数字的阶乘
返回一个给定整数的阶乘。
function factorialize(num) {
if (num === 0) {
return 1;
}
return num * factorialize(num - 1);
}
factorialize(5);
function factorialize(num) {
for (var product = 1; num > 0; num--) {
product *= num;
}
return product;
}
function factorialize(num, factorial = 1) {
if (num == 0) {
return factorial;
} else {
return factorialize(num - 1, factorial * num);
}
}
function factorialize(num, factorial = 1) {
return num < 0 ? 1 : (
new Array(num)
.fill(undefined)
.reduce((product, val, index) => product * (index + 1), 1)
);
}
4. 查找字符串中最长的单词
返回给出的句子中最长的单词的长度。你的返回应该是一个数字。
function findLongestWordLength(str) {
let newArr = str.split(' ')
let max = 0
for (let i = 0; i < newArr.length; i++) {
if(newArr[i].length > max) {
max = newArr[i].length
}
}
return max;
}
findLongestWordLength("The quick brown fox jumped over the lazy dog");
function findLongestWordLength(s) {
return s.split(' ')
.reduce(function(longest, word) {
return Math.max(longest, word.length)
}, 0);
}
function findLongestWordLength(str) {
return Math.max(...str.split(" ").map(word => word.length));
}
function findLongestWordLength(str) {
const words = str.split(" ");
if (words.length == 1) {
return words[0].length;
}
return Math.max(
words[0].length,
findLongestWordLength(words.slice(1).join(" "))
);
}
5. 返回数组中最大的数字
返回一个数组,它要由给出的所有子数组中的最大值组成。
function getMax(arr) {
return arr.sort((a, b) => b - a)[0]
}
function largestOfFour(arr) {
let result = []
for (let i = 0; i < arr.length; i++) {
let maxNum = getMax(arr[i])
result.push(maxNum)
}
return result;
}
function largestOfFour(arr) {
let results = [];
for (let i = 0; i < arr.length; i++) {
let largestNumber = arr[i][0];
for (let j = 1; j < arr[i].length; j++) {
if (arr[i][j] > largestNumber) {
largestNumber = arr[i][j];
}
}
results[i] = largestNumber;
}
return results;
}
function largestOfFour(arr) {
return arr.map(function(group) {
return group.reduce(function(prev, current) {
return current > prev ? current : prev;
});
});
}
function largestOfFour(arr) {
return arr.map(Function.apply.bind(Math.max, null));
}
function largestOfFour(arr, finalArr = []) {
return !arr.length
? finalArr
: largestOfFour(arr.slice(1), finalArr.concat(Math.max(...arr[0])))
}
6. 检查字符串的结尾
检查一个字符串(第一个参数,
str
)是否以给定的字符串(第二个参数target
)结束。请不要使用 ES6 的.endsWith()
方法
function confirmEnding(str, target) {
let len = target.length
let result = str.substring(str.length - len)
return result === target;
}
confirmEnding("Bastian", "n");
function confirmEnding(str, target) {
return str.slice(str.length - target.length) === target;
}
function confirmEnding(str, target) {
let re = new RegExp(target + "$", "i");
return re.test(str);
}
function confirmEnding(str, target) {
return str.slice(-target.length) === target
}
7. 重复字符串
将一个给定的字符串(第一个参数,
str
)重复num
(第二个参数)次。如果num
不是一个正数,返回一个空字符串。
function repeatStringNumTimes(str, num) {
let result = ''
if (num < 0) {
return ''
}
for (let i = 0; i < num; i++) {
result += str
}
return result
}
function repeatStringNumTimes(str, num) {
if (num < 1) {
return "";
} else {
return str + repeatStringNumTimes(str, num - 1);
}
}
function repeatStringNumTimes(str, num) {
return num > 0 ? str + repeatStringNumTimes(str, num - 1) : '';
}
8. 截断字符串
如果一个字符串(第一个参数)的长度大于给出的值(第二个参数),则截断它并在其后加上
...
。返回被截断的字符串。
function truncateString(str, num) {
if (str.length > num) {
return str.slice(0, num) + "...";
} else {
return str;
}
}
truncateString("A-tisket a-tasket A green and yellow basket", 8);
function truncateString(str, num) {
return str.length > num ? str.slice(0, num) + "..." : str;
}
9. 发现者与看护者
请写一个函数来检查一个数组(第一个参数)中的元素,并返回数组中第一个通过校验测试(第二个参数,一个接受一个参数并返回一个布尔值的函数)的元素。如果没有元素通过测试,则返回 undefined。
function findElement(arr, func) {
let result = arr.filter((item) => {
return func(item)
})
return result.length === 0 ? undefined : result[0]
}
findElement([1, 2, 3, 4], num => num % 2 === 0);
function findElement(arr, func) {
let num = 0;
for (let i = 0; i < arr.length; i++) {
num = arr[i];
if (func(num)) {
return num;
}
}
return undefined;
}
function findElement(arr, func) {
return arr.find(func);
}
function findElement(arr, func) {
return arr[arr.map(func).indexOf(true)];
}
function findElement(arr, func) {
return arr.length && !func(arr[0])
? findElement(arr.slice(1), func)
: arr[0];
}
10. 真假测试
检查一个值是否是原始的布尔值(boolean)类型。返回 true 或者 false。布尔值原始类型为 true 或者 false。
function booWho(bool) {
let res = Object.prototype.toString.call(bool).split(' ')[1]
res = res.substring(0, res.length - 1).toLowerCase()
if (res === 'boolean') {
return true
} else {
return false
}
}
booWho(null);
function booWho(bool) {
return typeof bool === "boolean";
}
11. 单词的首字母大写
将给出的字符串中所有单词的第一个字母变成大写,并返回得到的字符串。请确保其余的字母是小写的。
function titleCase(str) {
let ary = str.split(' ').map((item) => item.toLowerCase())
return ary.map((item) => {
let left = item.slice(0, 1).toUpperCase()
let right = item.slice(1)
return left + right
}).join(' ')
}
titleCase("I'm a little tea pot");
String.prototype.replaceAt = function(index, character) {
return (
this.substr(0, index) + character + this.substr(index + character.length)
);
};
function titleCase(str) {
var newTitle = str.split(" ");
var updatedTitle = [];
for (var st in newTitle) {
updatedTitle[st] = newTitle[st]
.toLowerCase()
.replaceAt(0, newTitle[st].charAt(0).toUpperCase());
}
return updatedTitle.join(" ");
}
function titleCase(str) {
var convertToArray = str.toLowerCase().split(" ");
var result = convertToArray.map(function(val) {
return val.replace(val.charAt(0), val.charAt(0).toUpperCase());
});
return result.join(" ");
}
function titleCase(str) {
return str.toLowerCase().replace(/(^|\s)\S/g, L => L.toUpperCase());
}
12. slice 和 splice
请利用数组的
slice
和splice
方法,将第一个数组中的所有元素依次复制到第二个数组中。请从第二个数组中索引值为n
的地方开始插入。返回插入元素后的数组。输入的两个数组在函数执行前后要保持不变。
function frankenSplice(arr1, arr2, n) {
let arr3 = arr2.slice(0)
let left = arr3.splice(n)
let result = [].concat(arr3).concat(arr1).concat(left)
return result
}
frankenSplice([1, 2, 3], [4, 5, 6], 1);
function frankenSplice(arr1, arr2, n) {
let localArray = arr2.slice();
for (let i = 0; i < arr1.length; i++) {
localArray.splice(n, 0, arr1[i]);
n++;
}
return localArray;
}
function frankenSplice(arr1, arr2, n) {
let localArr = arr2.slice();
localArr.splice(n, 0, ...arr1);
return localArr;
}
13. 去除数组中的假值
从一个数组中移除所有假值(falsy values)。JavaScript 中的假值有
false
、null
、0
、""
、undefined
和NaN
。
function bouncer(arr) {
let newArr = []
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
newArr.push(arr[i])
}
}
return newArr
}
function bouncer(arr) {
return arr.filter(Boolean);
}
14. 我身在何处
返回数组(第一个参数)被排序后,将一个值(第二个参数)插入到该数组中而使数组保持有序的最小的索引。返回的值应该是一个数字。例如,
getIndexToIns([20,3,5], 19)
应该返回2
因为数组被排序后会变成[3,5,20]
,而19
小于20
(索引为 2)且大于5
(索引为 1)。
function getIndexToIns(arr, num) {
arr.push(num)
arr.sort((a, b) => a - b)
return arr.indexOf(num)
}
getIndexToIns([40, 60], 50);
function getIndexToIns(arr, num) {
arr.sort(function(a, b) {
return a - b;
});
for (var a = 0; a < arr.length; a++) {
if (arr[a] >= num) return a;
}
return arr.length;
}
function getIndexToIns(arr, num) {
let len = arr.length;
let smallerCount = 0;
for (let i = 0; i < len; i++) {
if (num > arr[i]) {
smallerCount++;
}
}
return smallerCount;
}
function getIndexToIns(arr, num) {
arr.sort(function(a, b) {
return a - b;
});
let i = 0;
while (num > arr[i]) {
i++;
}
return i;
}
function getIndexToIns(arr, num) {
let index = arr
.sort((curr, next) => curr - next)
.findIndex(currNum => num <= currNum);
return index === -1 ? arr.length : index;
}
function getIndexToIns(arr, num) {
return arr
.concat(num)
.sort((a, b) => a - b)
.indexOf(num);
}
function getIndexToIns(arr, num) {
return arr.filter(val => num > val).length;
}
15. 集合之间的关系
输入参数是一个有两个字符串元素的数组。如果第一个字符串中包含了第二个字符串中的所有字母,则返回 true。例如,
["hello", "Hello"]
应该返回 true 因为第一个字符串中包含了第二个字符串中出现的所有字母(忽略大小写)。而["hello", "hey"]
应该返回 false 因为第一个字符串 “hello” 没有包含字母 “y”。
function mutation(arr) {
let test = arr[1].toLowerCase();
let target = arr[0].toLowerCase();
for (let i = 0; i < test.length; i++) {
if (target.indexOf(test[i]) < 0) return false;
}
return true;
}
mutation(["hello", "hey"]);
function mutation(arr) {
return arr[1]
.toLowerCase()
.split("")
.every(function(letter) {
return arr[0].toLowerCase().indexOf(letter) != -1;
});
}
function mutation([ target, test ], i = 0) {
target = target.toLowerCase();
test = test.toLowerCase();
return i >= test.length
? true
: !target.includes(test[i])
? false
: mutation([ target, test ], i + 1);
}
16. 猴子吃香蕉
请写一个函数,将一个数组(第一个参数)分割成一组长度为
size
(第二个参数)的数组,然后在一个二维数组中返回这些结果。
function chunkArrayInGroups(arr, size) {
let newArr = [];
for (let i = 0; i < arr.length; i += size) {
newArr.push(arr.slice(i, i + size));
}
return newArr;
}
chunkArrayInGroups(["a", "b", "c", "d"], 2);
function chunkArrayInGroups(arr, size) {
let temp = [];
let result = [];
for (let a = 0; a < arr.length; a++) {
if (a % size !== size - 1) temp.push(arr[a]);
else {
temp.push(arr[a]);
result.push(temp);
temp = [];
}
}
if (temp.length !== 0) result.push(temp);
return result;
}
function chunkArrayInGroups(arr, size) {
let newArr = [];
let i = 0;
while (i < arr.length) {
newArr.push(arr.slice(i, i + size));
i += size;
}
return newArr;
}
function chunkArrayInGroups(arr, size) {
let newArr = [];
while (arr.length > 0) {
newArr.push(arr.splice(0, size));
}
return newArr;
}
function chunkArrayInGroups(arr, size) {
if (arr.length <= size) {
return [arr];
} else {
return [arr.slice(0, size)].concat(
chunkArrayInGroups(arr.slice(size), size)
);
}
}
中级练习题
1. 范围内的数字求和
给出一个含有两个数字的数组,我们需要写一个函数,让它返回这两个数字间所有数字(包含这两个数字)的总和。注意,较小数不一定总是出现在数组的第一个元素。
function sumAll(arr) {
let result = []
arr.sort((a, b) => a - b)
for (let i = arr[0]; i <= arr[1]; i++) {
result.push(i)
}
return result.reduce((a, b) => a + b)
}
sumAll([1, 4]);
2. 区分两个数组
比较两个数组,返回一个新的数组。这个新数组需要包含传入的两个数组所有元素中,仅在其中一个数组里出现的元素。如果某个元素同时出现在两个数组中,则不应包含在返回的数组里。换言之,我们需要返回这两个数组的对称差。
function diffArray(arr1, arr2) {
let newArr = [].concat(arr1).concat(arr2)
let hash = new Map()
for (let i = 0; i < newArr.length; i++) {
if (hash.has(newArr[i])) {
hash.set(newArr[i], hash.get(newArr[i]) + 1)
} else {
hash.set(newArr[i], 1)
}
}
let result = []
hash.forEach(function (value, key) {
if (value === 1) {
result.push(key)
}
})
return result
}
3. 瞄准和消灭
传给它的第一个参数是数组,我们称他为初始数组。后续的参数数量是不确定的,可能有一个或多个。你需要做的是,从初始数组中移除所有与后续参数相等的元素,并返回移除元素后的数组。
function destroyer(arr, ...rest) {
return arr.filter(item => {
return !rest.includes(item)
})
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
4. 罗密欧与朱丽叶
它接收两个参数:第一个参数是对象数组,第二个参数是一个对象。我们需要从对象数组中找出与第二个参数相等或包含第二个参数的所有对象,并以对象数组的形式返回。其中,相等的意思是原数组中的对象与第二个参数中对象的所有键值对完全相等;包含的意思是只要第二个参数中对象的所有键存在于原数组对象中,且它们对应的值相同即可。
比如,如果第一个参数是
[{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }]
,第二个参数是{ last: "Capulet" }
。那么你需要以对象数组的形式返回第一个参数中的第三个元素,因为它包含第二个参数中定义的键last
,且对应的值"Capulet"
相同
function whatIsInAName(collection, source) {
var srcKeys = Object.keys(source);
return collection.filter(function(obj) {
for (var i = 0; i < srcKeys.length; i++) {
if (
!obj.hasOwnProperty(srcKeys[i]) ||
obj[srcKeys[i]] !== source[srcKeys[i]]
) {
return false;
}
}
return true;
});
}
function whatIsInAName(collection, source) {
var srcKeys = Object.keys(source);
return collection.filter(function(obj) {
return srcKeys.every(function(key) {
return obj.hasOwnProperty(key) && obj[key] === source[key];
});
});
}
function whatIsInAName(collection, source) {
var srcKeys = Object.keys(source);
return collection.filter(function(obj) {
return srcKeys
.map(function(key) {
return obj.hasOwnProperty(key) && obj[key] === source[key];
})
.reduce(function(a, b) {
return a && b;
});
});
}
5. 短线连接格式
把一个字符串转换为“短线连接格式”。短线连接格式的意思是,所有字母都是小写,且用
-
连接。比如,对于Hello World
,应该转换为hello-world
;对于I love_Javascript-VeryMuch
,应该转换为i-love-javascript-very-much
。
function spinalCase(str) {
let reg = /\s+|_+/g
let result = str.replace(/([a-z])(A-Z)/g, '$1 $2')
return result.replace(reg, '-').toLowerCase()
}
function spinalCase(str) {
str = str.replace(/([a-z])([A-Z])/g, "$1 $2")
return str
.toLowerCase()
.split(/(?:_| )+/)
.join("-")
}
function spinalCase(str) {
return str
.split(/\s|_|(?=[A-Z])/)
.join("-")
.toLowerCase();
}
6. 儿童黑话
需要把一个英文单词的第一个辅音字母或第一组辅音从移到单词的结尾,并在后面加上
ay
即可。在英语中,字母 a、e、i、o、u 为元音,其余的字母均为辅音。辅音从的意思是连续的多个辅音字母。额外地,如果单词本身是以元音开头的,那只需要在结尾加上
way
。
function translatePigLatin(str) {
let reg = /^[^aeiou]+/
let content = str.match(reg)
return content !== null ? str.replace(reg, '').concat(content).concat('ay') : str.concat('way')
}
function translatePigLatin(str) {
var pigLatin = ""
var regex = /[aeiou]/gi
if (str[0].match(regex)) {
pigLatin = str + "way"
} else if (str.match(regex) === null) {
pigLatin = str + "ay"
} else {
var vowelIndice = str.indexOf(str.match(regex)[0])
pigLatin = str.substr(vowelIndice) + str.substr(0, vowelIndice) + "ay"
}
}
function translatePigLatin(str) {
if (str.match(/^[aeiou]/)) return str + 'way'
const tempStr = str.match(/^[^aeiou]+/)[0]
return str.substring(tempStr.length) + tempStr + 'ay'
}
function translatePigLatin(str) {
return str
.replace(/^[aeiou]\w*/, "$&way")
.replace(/(^[^aeiou]+)(\w*)/, "$2$1ay")
}
function translatePigLatin(str, charPos = 0) {
return ['a', 'e', 'i', 'o', 'u'].includes(str[0])
? str + (charPos === 0 ? 'way' : 'ay')
: charPos === str.length
? str + 'ay'
: translatePigLatin(str.slice(1) + str[0], charPos + 1);
}
7. 搜索和替换
写一个字符串的搜索与替换函数,它的返回值为完成替换后的新字符串。这个函数接收的第一个参数为待替换的句子。第二个参数为句中需要被替换的单词。第三个参数为替换后的单词。
**注意:**你需要保留被替换单词首字母的大小写格式。即如果传入的第二个参数为 “Book”,第三个参数为 “dog”,那么替换后的结果应为 “Dog”
function myReplace(str, before, after) {
var index = str.indexOf(before);
if (str[index] === str[index].toUpperCase()) {
after = after.charAt(0).toUpperCase() + after.slice(1);
} else {
after = after.charAt(0).toLowerCase() + after.slice(1);
}
str = str.replace(before, after);
return str;
}
function myReplace(str, before, after) {
if (/^[A-Z]/.test(before)) {
after = after[0].toUpperCase() + after.substring(1)
} else {
after = after[0].toLowerCase() + after.substring(1)
}
return str.replace(before, after);
}
function myReplace(str, before, after) {
function applyCasing(source, target) {
var targetArr = target.split("");
var sourceArr = source.split("");
for (var i = 0; i < Math.min(targetArr.length, sourceArr.length); i++) {
if (/[A-Z]/.test(sourceArr[i])) {
targetArr[i] = targetArr[i].toUpperCase();
}
else targetArr[i] = targetArr[i].toLowerCase();
}
return targetArr.join("");
}
return str.replace(before, applyCasing(before, after));
}
String.prototype.capitalize =
String.prototype.capitalize ||
function () {
return this[0].toUpperCase() + this.slice(1);
};
const Util = (function () {
function textCase(str, tCase) {
if (tCase) {
return setCase(str, tCase);
} else {
return getCase(str);
}
function setCase(str, tCase) {
switch (tCase) {
case "uppercase":
return str.toUpperCase();
case "lowercase":
return str.toLowerCase();
case "capitalized":
return str.capitalize();
default:
return str;
}
}
function getCase(str) {
if (str === str.toUpperCase()) {
return "uppercase";
}
if (str === str.toLowerCase()) {
return "lowercase";
}
if (str === str.capitalize()) {
return "capitalized";
}
return "normal";
}
}
return {
textCase
};
})();
function myReplace(str, before, after) {
const { textCase } = Util;
const regex = new RegExp(before, "gi");
const replacingStr = textCase(after, textCase(before));
return str.replace(regex, replacingStr);
}
function myReplace(str, before, after) {
const myArr = str.split(" ");
const [wordToReplace] = myArr.filter(item => item === before);
return wordToReplace[0].toUpperCase() !== wordToReplace[0]
? myArr.map(item => (item === before ? after : item)).join(" ")
: myArr
.map(item =>
item === before ? after[0].toUpperCase() + after.slice(1) : item
)
.join(" ");
}
8. DNA 配对
为 DNA 中的碱基配对。这个函数只接收一个表示碱基的字符串为参数,最后返回完成配对的二维数组。
比如,传入的参数是 GCG,那么函数的返回值应为 [[“G”, “C”], [“C”,“G”],[“G”, “C”]]
function pairElement(str) {
let result = []
let arr = str.split('')
for (let i = 0; i < arr.length; i++) {
switch (arr[i]) {
case 'A': result.push(['A', 'T'])
break
case 'T': result.push(['T', 'A'])
break
case 'G': result.push(['G', 'C'])
break
case 'C': result.push(['C', 'G'])
break
}
}
return result
}
function pairElement(str) {
var pairs = {
A: "T",
T: "A",
C: "G",
G: "C"
};
var arr = str.split("");
return arr.map(x => [x, pairs[x]]);
}
9. 丢失的字母
判断缺失的依据是字母顺序,比如 abcdfg 中缺失了 e。而 abcdef 中就没有字母缺失,此时我们需要返回
undefined
。
function fearNotLetter(str) {
for (var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i)
if (code !== str.charCodeAt(0) + i) {
return String.fromCharCode(code - 1)
}
}
return undefined
}
function fearNotLetter(str) {
var compare = str.charCodeAt(0),
missing;
str.split("").map(function(letter, index) {
if (str.charCodeAt(index) == compare) {
++compare;
} else {
missing = String.fromCharCode(compare);
}
});
return missing;
}
function fearNotLetter(str) {
for (let i = 1; i < str.length; ++i) {
if (str.charCodeAt(i) - str.charCodeAt(i - 1) > 1) {
return String.fromCharCode(str.charCodeAt(i - 1) + 1);
}
}
}
10. 集合排序
function uniteUnique(...args) {
let ary = []
for (let i = 0; i < args.length; i++) {
ary = ary.concat(args[i])
}
let result = new Set(ary)
return [...result]
}
function uniteUnique(arr1, arr2, arr3) {
var finalArray = [];
for (var i = 0; i < arguments.length; i++) {
var arrayArguments = arguments[i];
for (var j = 0; j < arrayArguments.length; j++) {
var indexValue = arrayArguments[j];
if (finalArray.indexOf(indexValue) < 0) {
finalArray.push(indexValue);
}
}
}
return finalArray;
}
function uniteUnique(arr) {
var args = [...arguments];
var result = [];
for (var i = 0; i < args.length; i++) {
for (var j = 0; j < args[i].length; j++) {
if (!result.includes(args[i][j])) {
result.push(args[i][j]);
}
}
}
return result;
}
function uniteUnique() {
var newArr
var args = Array.prototype.slice.call(arguments)
newArr = args.reduce(function(arrA, arrB) {
return arrA.concat(
arrB.filter(function(i) {
return arrA.indexOf(i) === -1
})
)
})
return newArr
}
function uniteUnique() {
var concatArr = [];
var i = 0;
while (arguments[i]) {
concatArr = concatArr.concat(arguments[i]);
i++;
}
uniqueArray = concatArr.filter(function (item, pos) {
return concatArr.indexOf(item) == pos;
});
return uniqueArray;
}
function uniteUnique(...arrays) {
const flatArray = [].concat(...arrays)
return [...new Set(flatArray)]
}
function uniteUnique(...arr) {
return [...new Set(arr.flat())]
}
const uniteUnique = (...arr) => [...new Set(arr.flat())]
11. 转换HTML实体
function convertHTML(str) {
var temp = str.split("")
for (var i = 0; i < temp.length; i++) {
switch (temp[i]) {
case "<":
temp[i] = "<";
break;
case "&":
temp[i] = "&";
break;
case ">":
temp[i] = ">";
break;
case '"':
temp[i] = """;
break;
case "'":
temp[i] = "'";
break;
}
}
temp = temp.join("");
return temp;
}
function convertHTML(str) {
const htmlEntities = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'"
}
return str.replace(/([&<>\"'])/g, match => htmlEntities[match])
}
function convertHTML(str) {
const htmlEntities = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'"
};
return str
.split("")
.map(entity => htmlEntities[entity] || entity)
.join("");
}
12. 求斐波那契数组中的奇数之和
sumFibs(10)
应该返回10
。因为斐波那契数列中,比10
小的数字只有 1、1、3、5。
function sumFibs(num) {
let prevNumber = 0;
let currNumber = 1;
let result = 0;
while (currNumber <= num) {
if (currNumber % 2 !== 0) {
result += currNumber;
}
currNumber += prevNumber;
prevNumber = currNumber - prevNumber;
}
return result;
}
function sumFibs(num) {
if (num <= 0) return 0;
const arrFib = [1, 1];
let nextFib = 0;
while ((nextFib = arrFib[0] + arrFib[1]) <= num) {
arrFib.unshift(nextFib);
}
return arrFib.filter(x => x % 2 != 0).reduce((a, b) => a + b);
}
13. 对所有素数求和
function isPrime(n) {
let flag = n < 2 ? false : true
for (let i = 2, max = Math.sqrt(n); i <= max; i++) {
if ( n % i === 0) {
flag = false
break
}
}
return flag
}
function sumPrimes(num) {
let result = [2]
for (let i = 3; i <= num; i++) {
if (isPrime(i)) {
result.push(i)
}
}
return result.reduce((a, b) => a + b)
}
function sumPrimes(num) {
let primes = [];
for (let i = 2; i <= num; i++) {
if (primes.every((prime) => i % prime !== 0))
primes.push(i);
}
return primes.reduce((sum, prime) => sum + prime, 0);
}
function sumPrimes(num) {
let isPrime = Array(num + 1).fill(true);
isPrime[0] = false;
isPrime[1] = false;
for (let i = 2; i <= Math.sqrt(num); i++) {
if (isPrime[i]) {
for (let j = i * i; j <= num; j += i)
isPrime[j] = false;
}
}
return isPrime.reduce(
(sum, prime, index) => prime ? sum + index : sum, 0
);
}
14. 最小公倍数
function smallestCommons(arr) {
const [min, max] = arr.sort((a, b) => a - b);
const numberDivisors = max - min + 1;
let upperBound = 1;
for (let i = min; i <= max; i++) {
upperBound *= i;
}
for (let multiple = max; multiple <= upperBound; multiple += max) {
let divisorCount = 0;
for (let i = min; i <= max; i++) {
if (multiple % i === 0) {
divisorCount += 1;
}
}
if (divisorCount === numberDivisors) {
return multiple;
}
}
}
function smallestCommons(arr) {
const [min, max] = arr.sort((a, b) => a - b);
const range = Array(max - min + 1)
.fill(0)
.map((_, i) => i + min);
const upperBound = range.reduce((prod, curr) => prod * curr)
for (let multiple = max; multiple <= upperBound; multiple += max) {
const divisible = range.every((value) => multiple % value === 0)
if (divisible) {
return multiple
}
}
}
function smallestCommons(arr) {
const [min, max] = arr.sort((a, b) => a - b)
const range = Array(max - min + 1)
.fill(0)
.map((_, i) => i + min)
const gcd = (a, b) => (b === 0) ? a : gcd(b, a % b)
const lcm = (a, b) => a * b / gcd(a, b)
return range.reduce((multiple, curr) => lcm(multiple, curr))
}
function smallestCommons(arr) {
let primeFactors = {};
const [min, max] = arr.sort((a, b) => a - b);
for (let i = min; i <= max; i++) {
let primes = getPrimeFactors(i);
for (let j in primes) {
if (!primeFactors[j] || primes[j] > primeFactors[j]) {
primeFactors[j] = primes[j]
}
}
}
let multiple = 1;
for (let i in primeFactors) {
multiple *= i ** primeFactors[i]
}
return multiple;
}
function getPrimeFactors(num) {
const factors = {};
for (let prime = 2; prime <= num; prime++) {
while ((num % prime) === 0) {
factors[prime] = (factors[prime]) ? factors[prime] + 1 : 1;
num /= prime;
}
}
return factors;
}
15. 放弃
function dropElements(arr, func) {
while (arr.length > 0 && !func(arr[0])) {
arr.shift();
}
return arr;
}
function dropElements(arr, func) {
let sliceIndex = arr.findIndex(func)
return arr.slice(sliceIndex >= 0 ? sliceIndex : arr.length)
}
function dropElements(arr, func) {
let originalLen = arr.length
for (let i = 0; i < originalLen; i++) {
if (func(arr[0])) {
break
} else {
arr.shift()
}
}
return arr
}
function dropElements(arr, func, i = 0) {
return i < arr.length && !func(arr[i])
? (dropElements(arr.slice(i + 1), func, i))
: arr
}
16. 扁平化
function steamrollArray(arr) {
let result = []
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(steamrollArray(arr[i]))
} else {
result = result.concat(arr[i])
}
}
return result
}
function steamrollArray(arr) {
const flat = [].concat(...arr);
return flat.some(Array.isArray) ? steamrollArray(flat) : flat;
}
function steamrollArray(arr) {
return arr
.toString()
.replace(",,", ",") // "1,2,,3" => "1,2,3"
.split(",") // ['1','2','3']
.map(function(v) {
if (v == "[object Object]") {
return {};
} else if (isNaN(v)) {
return v;
} else {
return parseInt(v)
}
})
}
function steamrollArray(val,flatArr=[]) {
val.forEach(item => {
if (Array.isArray(item)) steamrollArray(item, flatArr)
else flatArr.push(item)
});
return flatArr
}
function steamrollArray(arr, flatArr = []) {
const elem = arr.pop();
return elem
? !Array.isArray(elem)
? steamrollArray(arr, [elem, ...flatArr])
: steamrollArray(arr.concat(elem), flatArr)
: flatArr;
}
17. 二进制转化
function binToAscii(num) {
var str1 = '';
if (typeof num != 'String') {
var str = num.toString();
}
var Hlong = Math.ceil(str.length / 8);
for (var i = 0; i < Hlong; i++) {
str1 += String.fromCharCode(parseInt(str.substring(i * 8, (i + 1) * 8), 2));
}
return str1;
}
function binaryAgent(str) {
let result = []
let ary = str.split(' ')
for (let i = 0; i < ary.length; i++) {
result.push(binToAscii(ary[i]))
}
return result.join('')
}
function binaryAgent(str) {
var biString = str.split(" ");
var uniString = [];
for (var i = 0; i < biString.length; i++) {
uniString.push(String.fromCharCode(parseInt(biString[i], 2)));
}
return uniString.join("");
}
function binaryAgent(str) {
str = str.split(" ")
var power
var decValue = 0
var sentence = ""
for (var s = 0; s < str.length; s++) {
for (var t = 0; t < str[s].length; t++) {
if (str[s][t] == 1) {
power = Math.pow(2, +str[s].length - t - 1)
decValue += power
}
}
sentence += String.fromCharCode(decValue)
decValue = 0
}
return sentence
}
function binaryAgent(str) {
return String.fromCharCode(
...str.split(" ").map(function(char) {
return parseInt(char, 2);
})
);
}
18. 真假值判断
一个函数,它接收两个参数。第一个参数为对象数组
collection
,第二个参数为一个字符串pre
,代表对象的一个键(key)。我们需要检查对象数组中每个对象的pre
属性对应的值是否都为 “真”(truthy)。如果是,则返回true
,否则返回false
。
function truthCheck(collection, pre) {
let counter = 0
for (let c in collection) {
if (collection[c].hasOwnProperty(pre) && Boolean(collection[c][pre])) {
counter++
}
}
return counter === collection.length
}
function truthCheck(collection, pre) {
return collection.every(function(element) {
return element.hasOwnProperty(pre) && Boolean(element[pre]);
})
}
function truthCheck(collection, pre) {
return collection.every(obj => obj[pre]);
}
19. 可选参数
一个求和的函数,但它接收的参数数量不定。如果传入了两个参数,那么直接返回两数之和即可。如果只传入一个参数,那我们应该返回另一个函数用来接收下一个参数,然后求出两数之和。
比如,
addTogether(2, 3)
应该返回5
。而addTogether(2)
应该返回一个函数。然后我们调用这个返回的函数,并给它传入另一个用于求和的值:
var sumTwoAnd = addTogether(2);
sumTwoAnd(3)
此时应返回5
。只要其中任何一个参数不是数字,那我们就应返回
undefined
。
function addTogether() {
function checkNum(num) {
return (typeof num === "number");
};
if (arguments.length === 2) {
let first = arguments[0];
let second = arguments[1];
if (checkNum(first) && checkNum(second)) {
return first + second;
} else {
return undefined;
}
} else if (arguments.length === 1) {
let first = arguments[0];
if (checkNum(first)) {
function addSecond(second) {
if (checkNum(second)) {
return first + second;
} else {
return undefined;
}
};
return addSecond;
} else {
return undefined;
}
} else {
return undefined;
}
}
function addTogether() {
const [first, second] = Object.values(arguments);
if (typeof first !== "number") {
return undefined;
}
const addSecond = (second) => typeof second === "number" ? first + second : undefined;
if (second !== undefined) {
return addSecond(second);
} else {
return addSecond
}
}
function addTogether() {
var args = Array.from(arguments);
return args.some(n => typeof n !== "number")
? undefined
: args.length > 1
? args.reduce((acc, n) => (acc += n), 0)
: n => (typeof n === "number" ? n + args[0] : undefined);
}
20. 构造一个 Person 类
getFirstName() getLastName() getFullName() setFirstName(first) setLastName(last) setFullName(firstAndLast)
var Person = function (firstAndLast) {
var fullName = firstAndLast
this.getFirstName = function () {
return fullName.split(" ")[0]
}
this.getLastName = function () {
return fullName.split(" ")[1]
}
this.getFullName = function () {
return fullName
}
this.setFirstName = function (name) {
fullName = name + " " + fullName.split(" ")[1]
}
this.setLastName = function (name) {
fullName = fullName.split(" ")[0] + " " + name
}
this.setFullName = function (name) {
fullName = name
}
}
21. 绘制碎片图
写一个计算天体轨道周期的函数,它接收一个对象数组参数
arr
,对象中包含表示天体名称的name
属性,及表示轨道半长轴的avgAlt
属性。就像这样:{name: 'name', avgAlt: avgAlt}
。这个函数的返回值也是一个对象数组,应保留原对象中的
name
属性和值,然后根据avgAlt
属性的值求出轨道周期(单位是秒),并赋值给orbitalPeriod
属性。返回值中不应保留原数据中的avgAlt
属性及其对应的值。
function orbitalPeriod(arr) {
var GM = 398600.4418;
var earthRadius = 6367.4447;
var a = 2 * Math.PI;
var newArr = [];
var getOrbPeriod = function(obj) {
var c = Math.pow(earthRadius + obj.avgAlt, 3);
var b = Math.sqrt(c / GM);
var orbPeriod = Math.round(a * b);
return {name: obj.name, orbitalPeriod: orbPeriod};
};
for (var elem in arr) {
newArr.push(getOrbPeriod(arr[elem]));
}
return newArr;
}
function orbitalPeriod(arr) {
var GM = 398600.4418;
var earthRadius = 6367.4447;
var newArr = [];
for (var elem in arr) {
var orbitalPer = Math.round(
2 * Math.PI * Math.sqrt(Math.pow(arr[elem].avgAlt + earthRadius, 3) / GM)
);
newArr.push({name: arr[elem].name, orbitalPeriod: orbitalPer});
}
return newArr;
}
function orbitalPeriod(arr) {
var GM = 398600.4418;
var earthRadius = 6367.4447;
var newArr = JSON.parse(JSON.stringify(arr));
newArr.forEach(function(item) {
var tmp = Math.round(
2 * Math.PI * Math.sqrt(Math.pow(earthRadius + item.avgAlt, 3) / GM)
);
delete item.avgAlt;
item.orbitalPeriod = tmp;
});
return newArr;
}
function orbitalPeriod(arr) {
const GM = 398600.4418;
const earthRadius = 6367.4447;
return arr.map(({ name, avgAlt }) => {
const earth = earthRadius + avgAlt;
const orbitalPeriod = Math.round(2 * Math.PI * Math.sqrt(Math.pow(earth, 3)/GM));
return { name, orbitalPeriod };
});
}
22. 回文检查器
function palindrome(str) {
let reg = /\W+/g
let s = str.replace(reg, '').replace('_', '').toLowerCase()
return s === s.split('').reverse().join('');
}
function palindrome(str) {
let reg = /\W+/g
let s = str.replace(reg, '').replace('_', '').toLowerCase()
let left = 0, right = s.length - 1
while (left < right) {
if (s[left] !== s[right]) {
return false
}
left++
right--
}
return true
}
23. 找到对等分差
知识提要:对称差 (Symmetric Difference),数学上,两个集合的对称差分是只属于其中一个集合,而不属于另一个集合的元素组成的集合,例如:集合
let A = [ 1, 2, 3]
和let B = [ 2, 3, 4]
的对称差分为A △ B = C = [ 1, 4]
。 集合论中的这个运算相当于布尔逻辑中的异或运算。创建一个函数 sym,输入两个或两个以上的数组作为参数,然后返回值为对称差分的数组
思路:设定两个数组 (例如:
let A = [1, 2, 3]
,let B = [2, 3, 4]
)作为参数传入,返回对称差分数组(A △ B = C = [1, 4]
),且数组中没有重复项。(传入的数组个数是不定参数)
function sym() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
function symDiff(arrayOne, arrayTwo) {
var result = [];
arrayOne.forEach(function(item) {
if (arrayTwo.indexOf(item) < 0 && result.indexOf(item) < 0) {
result.push(item);
}
});
arrayTwo.forEach(function(item) {
if (arrayOne.indexOf(item) < 0 && result.indexOf(item) < 0) {
result.push(item);
}
});
return result;
}
return args.reduce(symDiff);
}