JavaScript专项算法题(2):函数式编程

简介: 问题:构建一个addTwo函数,作用为接受一个参数并将参数加2。题解:12345678// Challenge 1const addTwo = (num) => { return num + 2;};// To check if you've completed this function, uncomment these console.logs!console.log(addTwo(3));console.log(addTwo(10));挑战2 addS问题:构建一个addS函数,作用为接受一个参数并将参数与“s”拼接。题解:12

问题:

构建一个addTwo函数,作用为接受一个参数并将参数加2。

题解:

1
2
3
4
5
6
7
8
// Challenge 1
const addTwo = (num) => {
return num + 2;
};
// To check if you've completed this function, uncomment these console.logs!
console.log(addTwo(3));
console.log(addTwo(10));

挑战2 addS

问题:

构建一个addS函数,作用为接受一个参数并将参数与“s”拼接。

题解:

1
2
3
4
5
6
7
8
// Challenge 2
const addS = (word) => {
return word.toString() + 's';
};
// Uncomment these to check your work
console.log(addS('pizza'));
console.log(addS('bagel'));

挑战3 map

问题:

构建一个map函数,其接受两个参数:

  1. 数值型数组
  2. 回调函数——一个应用于上述数值型数组中的每一个元素的函数(于map函数内)

map函数的返回值为包含上述数值型数组元素逐个运行回调函数后生成的元素值的新数组。

1
2
3
map([1,2,3,4,5], multiplyByTwo); //-> [2,4,6,8,10]
multiplyByTwo(1); //-> 2
multiplyByTwo(2); //-> 4

题解:

1
2
3
4
5
6
7
8
9
10
// Challenge 3
const map = (array, callback) => {
const newArray = [];
for(let i = 0; i< array.length; i++){
    newArray.push(callback(array[i]));
  }
return newArray;
};
console.log(map([1, 2, 3], addTwo));

挑战4 forEach

问题:

函数forEach接受一个数组和一个回调函数,运行回调函数于输入数组的每一个元素。forEach函数无返回值。

1
2
3
4
let alphabet = '';
const letters = ['a', 'b', 'c', 'd'];
forEach(letters, char => alphabet += char);
console.log(alphabet);   //prints 'abcd'

题解:

1
2
3
4
5
6
7
8
9
10
11
12
// Challenge 4
const forEach = (array, callback) => {
for(let i = 0; i<array.length; i++){
    callback(array[i]);
  }
};
// See for yourself if your forEach works!
let alphabet = '';
const letters = ['a', 'b', 'c', 'd'];
forEach(letters, char => alphabet += char);
console.log(alphabet);   //prints 'abcd'

挑战5 mapWith

问题:

在这个挑战中,你需要将map函数重构为mapWith。这一次你要在mapWith中使用forEach函数而不是使用for循环。

题解:

1
2
3
4
5
6
7
// Challenge 5
const mapWith = (array, callback) => {
const newArray = newArray;
  forEach(array, el => newArray.push(callback(el)));
return newArray;
};
console.log(mapWith([1, 2, 3], addTwo));

挑战6 reduce

问题:

函数reduce接受一个数组并将数组内的所有值合并为一个值。比如,它可以将数组求和,求积,以及其它你想加进函数中的操作。

1
2
3
const nums = [4, 1, 3];
const add = (a, b) => a + b; 
reduce(nums, add, 0);   //-> 8

以下是它的运行原理。函数有一个“累加器值”(第三个参数),作用为充当初始值并且累加每一次循环的输出值。数组参数会被遍历,传递“累加器值“和新的数组元素值作为参数到回调函数中。回调函数的返回值会成为新的”累加器值“。下一个循环会使用这个新”累加器值“。在上面的例子中,”累加器值“刚开始为0,调用add(0, 4),”累加器值“变为4,然后add(4, 1)将其变为5,最后add(5, 3)得到8并最终返回。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
// Challenge 6
const reduce = (array, callback, initialValue) => {
let newValue = initialValue;
for(let i = 0; i<array.length; i++){
    newValue = callback(newValue, array[i]);
  }
return newValue;
};
const nums = [4, 1, 3];
const add = (a, b) => a + b; 
console.log(reduce(nums, add, 0));   //-> 8

挑战7 intersection

问题:

构建intersection函数,作用为比较输入进来的多组数组并返回一个包含数组间共同元素的新数组。奖励:使用reduce!

题解:

1
2
3
4
5
6
7
8
9
// Challenge 7
const intersection = (arrays) => {
return arrays.reduce((acc, curr) => {
return curr.filter(el => acc.includes(el));
  })
};
console.log(intersection([[5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20]]));
// should log: [5, 15]

挑战8 union

问题:

构建union函数,作用为比较输入进来的多组数组并返回一个包含输入数组中所有元素的新数组。如果存在重复元素,则新数组中仅保留一个,另外需保留新数组的元素顺序为从第一个输入数组的第一个元素开始。奖励:使用reduce!

题解:

1
2
3
4
5
6
7
8
9
10
// Challenge 8
const union = (arrays) => {
return arrays.reduce((acc, curr) => {
// acc.push(curr.filter(el => !acc.includes(el)));
return acc.concat(curr.filter(el => !acc.includes(el)));
  })
};
console.log(union([[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]]));
// should log: [5, 10, 15, 88, 1, 7, 100]

挑战9 objOfMatches

问题:

构建objOfMatches函数,接受两个数组和一个回调函数作为参数,作用为创建一个特定对象并返回。objOfMatches会使用回调函数测试第一个数组的每一个元素以确认其输出是否匹配于第二个数组内相同下标的元素。如果匹配,第一个数组内的这个元素会成为所创建对象的键,而第二个数组内的相同下标元素则会成为对应的值。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Challenge 9
const objOfMatches = (array1, array2, callback) => {
const matchObj = {};
for(let i =0; i<array1.length; i++){
if(callback(array1[i])===array2[i]){
      matchObj[array1[i]] = array2[i];
    }
  }
return matchObj;
};
console.log(objOfMatches(['hi', 'howdy', 'bye', 'later', 'hello'], ['HI', 'Howdy', 'BYE', 'LATER', 'hello'], (str) => str.toUpperCase()));
// should log: { hi: 'HI', bye: 'BYE', later: 'LATER' }

挑战10 multiMap

问题:

构建multiMap函数,接受两个数组作为参数,第一个数组的元素为值而第二个数组的元素为回调函数。multiMap会返回一个特定对象,该对象的键为第一个数组的值,键对应的值则是将键依序传入第二个数组的回调函数中得到的返回值组成的新数组。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Challenge 10
const multiMap = (arrVals, arrCallbacks) => {
const multiMapObj = {};
let tempArray = [];
  arrVals.forEach(el => {
    tempArray = [];
for(let i=0; i<arrCallbacks.length; i++){
      tempArray.push(arrCallbacks[i](el));
    }
    multiMapObj[el] = tempArray;
  })
return multiMapObj;
};
console.log(multiMap(['catfood', 'glue', 'beer'], [(str) => str.toUpperCase(), (str) => str[0].toUpperCase() + str.slice(1).toLowerCase(), (str) => str + str]));
// should log: { catfood: ['CATFOOD', 'Catfood', 'catfoodcatfood'], glue: ['GLUE', 'Glue', 'glueglue'], beer: ['BEER', 'Beer', 'beerbeer'] }

挑战11 commutative

问题:

构建commutative函数,接受参数为两个回调函数和一个值。commutative会返回一个布尔值,从而表明运行第一个回调函数于输入值,再将得到的返回值输入到第二个回调函数中运行,得到的结果与逆序操作是否相同(即运行输入值于第二个回调函数,得到的返回值再输入到第一个回调函数中)。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Challenge 11
const commutative = (func1, func2, value) => {
if(func1(func2(value)) === func2(func1(value))){
returntrue;
  } else {
returnfalse;
  }
};
/*** Uncomment these to check your work! ***/
const multBy3 = n => n * 3;
const divBy4 = n => n / 4;
const subtract5 = n => n - 5;
console.log(commutative(multBy3, divBy4, 11)); // should log: true
console.log(commutative(multBy3, subtract5, 10)); // should log: false
console.log(commutative(divBy4, subtract5, 48)); // should log: false

挑战12 objectFilter

问题:

构建objectFilter函数,第一个参数为对象,第二个参数为回调函数。objectFilter函数会返回特定对象。此特定对象所包含的属性为输入对象中值与其对应键传入回调函数得到的返回值一致的键值对。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Challenge 12
const objFilter = (obj, callback) => {
const objectFilterObj = {};
for(let key in obj) {
if(obj[key] === callback(key)){
      objectFilterObj[key] = obj[key];
    }
  }
return objectFilterObj;
};
/*** Uncomment these to check your work! ***/
const startingObj = {};
startingObj[6] = 3;
startingObj[2] = 1;
startingObj[12] = 4;
const half = n => n / 2;
console.log(objFilter(startingObj, half)); // should log: { 2: 1, 6: 3 }

挑战13 rating

问题:

构建rating函数,接受参数为一个由函数组成的数组和一个值。数组中的函数的返回值皆为true或false。rating会返回一个表明将输入值运行于数组中的函数会返回true的百分比数。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Challenge 13
const rating = (arrOfFuncs, value) => {
let trueCounter = 0; 
    arrOfFuncs.forEach(el => {
if(el(value)){
       trueCounter++;
  	}
  })
return trueCounter/arrOfFuncs.length * 100;
};
/*** Uncomment these to check your work! ***/
const isEven = n => n % 2 === 0;
const greaterThanFour = n => n > 4;
const isSquare = n =>Math.sqrt(n) % 1 === 0;
const hasSix = n => n.toString().includes('6');
const checks = [isEven, greaterThanFour, isSquare, hasSix];
console.log(rating(checks, 64)); // should log: 100
console.log(rating(checks, 66)); // should log: 75

挑战14 pipe

问题:

构建pipe函数,接受参数为一个由函数组成的数组和一个值。pipe会将输入值输入到数组的第一个函数中,然后再将得到的输出值输入到第二个函数中,然后输出值又再输入到第三个函数中,一直下去,直到得到数组的最后一个函数的输出值。pipe会返回这个最终输出值。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Challenge 14
const pipe = (arrOfFuncs, value) => {
let output = value;
    arrOfFuncs.forEach(el => {
    output = el(output);
  })
return output;
};
/*** Uncomment these to check your work! ***/
const capitalize = str => str.toUpperCase();
const addLowerCase = str => str + str.toLowerCase();
const repeat = str => str + str;
const capAddlowRepeat = [capitalize, addLowerCase, repeat];
console.log(pipe(capAddlowRepeat, 'cat')); // should log: 'CATcatCATcat'

挑战15 highestFunc

问题:

构建highestFunc函数,接受参数为一个对象(包含函数)和一个值。highestFunc会返回输入对象中运行输入值后得到最高值的函数所对应的键。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Challenge 15
const highestFunc = (objOfFuncs, subject) => {
let maxKey = "";
let maxNumber = Number.NEGATIVE_INFINITY;
for(let key in objOfFuncs) {
if(objOfFuncs[key](subject) > maxNumber){
      maxNumber = objOfFuncs[key](subject);
      maxKey = key;
    }
  }
return maxKey;
};
/*** Uncomment these to check your work! ***/
const groupOfFuncs = {};
groupOfFuncs.double = n => n * 2;
groupOfFuncs.addTen = n => n + 10;
groupOfFuncs.inverse = n => n * -1;
console.log(highestFunc(groupOfFuncs, 5)); // should log: 'addTen'
console.log(highestFunc(groupOfFuncs, 11)); // should log: 'double'
console.log(highestFunc(groupOfFuncs, -20)); // should log: 'inverse'

闭包

挑战1 createFunction

问题:

构建createFunction函数,用于创建和返回函数。当被创建的函数被调用时,它会打印“hello”。

1
2
3
const function1 = createFunction();
// now we'll call the function we just created
function1(); //should console.log('hello');

题解:

1
2
3
4
5
6
7
8
9
10
11
// Challenge 1
const createFunction = () => {
const innerFunction = () => {
console.log('hello');
    }
return innerFunction;
};
// UNCOMMENT THESE TO TEST YOUR WORK!
const function1 = createFunction();
function1();

挑战2 createFunctionPrinter

问题:

构建接受一个输入值作为参数的createFunctionPrinter函数,用于创建和返回一个特定函数。当特定函数被调用时,其应该打印特定函数被创建时输入createFunctionPrinter中的值。

1
2
3
4
5
const printSample = createFunctionPrinter('sample');
const printHello = createFunctionPrinter('hello')
// now we'll call the functions we just created
printSample(); //should console.log('sample');
printHello(); //should console.log('hello');

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Challenge 2
const createFunctionPrinter = (input) => {
let inputValue = input;
const innerFunction = (inputValue) => {
console.log(input);
  }
return innerFunction;
};
// UNCOMMENT THESE TO TEST YOUR WORK!
const printSample = createFunctionPrinter('sample');
printSample();
const printHello = createFunctionPrinter('hello');
printHello();

挑战3 outer

问题:

观察下面outer函数的实现代码。注意其会返回一个函数而且那个函数使用了不在其作用域的变量。尝试推断一下运行outer函数得到的输出值。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Challenge 3
const outer = () => {
let counter = 0; // this variable is outside incrementCounter's scope
const incrementCounter = () => {
    counter++;
console.log('counter', counter);
  }
return incrementCounter;
};
const willCounter = outer();
const jasCounter = outer();
// Uncomment each of these lines one by one.
// Before your do, guess what will be logged from each function call.
willCounter();
willCounter();
willCounter();
jasCounter();
willCounter();

挑战4 addByX

问题:

构建addByX函数,其会返回一个接受一个输入值作为参数并与x相加的函数。

1
2
3
4
5
6
7
8
9
10
11
12
const addByTwo = addByX(2);
addByTwo(1); //should return 3
addByTwo(2); //should return 4
addByTwo(3); //should return 5
const addByThree = addByX(3);
addByThree(1); //should return 4
addByThree(2); //should return 5
const addByFour = addByX(4);
addByFour(4); //should return 8
addByFour(10); //should return 14

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Challenge 4
const addByX = (x) => {
const outerInput = x;
const innerFunction = (innerInput) => {
return x + innerInput;
  }
return innerFunction;
};
const addByTwo = addByX(2);
// now call addByTwo with an input of 1
console.log(addByTwo(1));
// now call addByTwo with an input of 2
console.log(addByTwo(2));

挑战5 once

问题:

构建once函数,接受参数为一个回调函数并返回一个特定函数。当特定函数被第一次调用时,其会调用回调函数并返回输出值。如果其不是被第一次调用,则特定函数仅仅返回第一次调用时得到的回调函数返回值,而不是再次运行回调函数。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Challenge 5
const once = (func) => {
let counter = 0;
let onceResult = 0;
const innerFunction = (el) => {
    counter++;
if(counter === 1) {
      onceResult = func(el);
return onceResult;
    } else{
return onceResult;
    }
  }
return innerFunction;
};
const onceFunc = once(addByTwo);
// UNCOMMENT THESE TO TEST YOUR WORK!
console.log(onceFunc(4));  //should log 6
console.log(onceFunc(10));  //should log 6
console.log(onceFunc(9001));  //should log 6

挑战6 after

问题:

构建after函数,接受一个数字n和一个回调函数作为参数。回调函数需要在通过after构建的函数运行第n次时才被运行。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Challenge 6
const after = (count, func) => {
let counter = count;
const innerFunction = (el) => {
if(--counter === 0){
      func(el);
    }
  }
return innerFunction;
};
const called = () =>console.log('hello');
const afterCalled = after(3, called);
afterCalled(); // -> nothing is printed
afterCalled(); // -> nothing is printed
afterCalled(); // -> 'hello' is printed

挑战7 delay

问题:

构建delay函数,作用为接受一个回调函数作为第一个参数,一个数值n(单位为毫秒)作为第二个参数,返回一个特定函数。delay构建的特定函数被调用后,须经n毫秒后才运行回调函数。任何其他赋给特定函数的参数会在n毫秒后被回调函数使用。提示:研究setTimeout();

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Challenge 7
const delay = (func, wait) => {
const waitTime = wait;
const innerFunction = (el) => {
  	setTimeout((el) => {
      func(el);
    }, waitTime);  
  }
return innerFunction;
};
const delayCalled = delay(called, 2000);
delayCalled(); // "hello" after 2 seconds.

挑战8 russianRoulette

问题:

构建russianRoulette函数,作用为接受一个数值参数(假设为n)并返回一个特定函数。此特定函数不接受输入参数,而且会在前n-1次调用时返回字符串“click“,在第n次调用时则返回字符串”bang“,n次以后再调用皆返回字符串”reload to play again”。

题解:

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
// Challenge 8
const russianRoulette = (num) => {
let counter = num;
const innerFunction = () => {
    counter--;
if(counter>0) {
return"click";
    } elseif(counter==0){
return"bang";
    } else{
return"reload to play again";
    }
  }
return innerFunction; 
};
/*** Uncomment these to check your work! ***/
const play = russianRoulette(3);
console.log(play()); // should log: 'click'
console.log(play()); // should log: 'click'
console.log(play()); // should log: 'bang'
console.log(play()); // should log: 'reload to play again'
console.log(play()); // should log: 'reload to play again'
// Challenge 8
const russianRoulette = (num) => {
let counter = num;
const innerFunction = () => {
    counter--;
if(counter>0) {
return"click";
    } elseif(counter==0){
return"bang";
    } else{
return"reload to play again";
    }
  }
return innerFunction; 
};
/*** Uncomment these to check your work! ***/
const play = russianRoulette(3);
console.log(play()); // should log: 'click'
console.log(play()); // should log: 'click'
console.log(play()); // should log: 'bang'
console.log(play()); // should log: 'reload to play again'
console.log(play()); // should log: 'reload to play again'

挑战9 average

问题:

构建average函数,不接受参数,并返回一个特定函数(接受一个数值作为参数或无参数)。当average创建的特定函数被输入数值参数的方式调用时,返回值为所有曾经被输入到特定函数的数值参数的平均值(重复数值视为分别的数值)。当特定函数被无参数的方式调用时,返回当前的平均值。如果特定函数在无参数方式调用时不曾被输入数值参数的方式调用过,则返回0。

题解:

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
// Challenge 9
const average = () => {
let averageValue = 0;
let argumentCounter = 0;
let argumentSum = 0;
const innerFunction = (el) => {
if(el == undefined) {
return averageValue;
    } else{
      argumentCounter++;
      argumentSum += el; 
      averageValue = argumentSum / argumentCounter;
return averageValue;
    }
  }
return innerFunction;
};
/*** Uncomment these to check your work! ***/
const avgSoFar = average();
console.log(avgSoFar()); // should log: 0
console.log(avgSoFar(4)); // should log: 4
console.log(avgSoFar(8)); // should log: 6
console.log(avgSoFar()); // should log: 6
console.log(avgSoFar(12)); // should log: 8
console.log(avgSoFar()); // should log: 8

挑战10 makeFuncTester

问题:

构建makeFuncTester函数,接受参数为一个二维数组(其中第二维数组仅含两个元素),返回一个接收回调函数作为参数的特定函数。当二维数组的每一个子数组的第一个元素输入到回调函数时都产生与第二个元素相同的返回值时,特定函数返回ture,

相关文章
|
1月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
56 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
3月前
|
JavaScript 算法 前端开发
JS算法必备之String常用操作方法
这篇文章详细介绍了JavaScript中字符串的基本操作,包括创建字符串、访问特定字符、字符串的拼接、位置查找、大小写转换、模式匹配、以及字符串的迭代和格式化等方法。
JS算法必备之String常用操作方法
|
3月前
|
JavaScript 算法 前端开发
JS算法必备之Array常用操作方法
这篇文章详细介绍了JavaScript中数组的创建、检测、转换、排序、操作方法以及迭代方法等,提供了数组操作的全面指南。
JS算法必备之Array常用操作方法
|
3月前
|
JavaScript 算法 前端开发
"揭秘Vue.js的高效渲染秘诀:深度解析Diff算法如何让前端开发快人一步"
【8月更文挑战第20天】Vue.js是一款备受欢迎的前端框架,以其声明式的响应式数据绑定和组件化开发著称。在Vue中,Diff算法是核心之一,它高效计算虚拟DOM更新时所需的最小实际DOM变更,确保界面快速准确更新。算法通过比较新旧虚拟DOM树的同层级节点,递归检查子节点,并利用`key`属性优化列表更新。虽然存在局限性,如难以处理跨层级节点移动,但Diff算法仍是Vue高效更新机制的关键,帮助开发者构建高性能Web应用。
67 1
|
4月前
|
数据采集 算法 JavaScript
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
JavaScript字符串搜索涵盖`indexOf`、`includes`及KMP算法。`indexOf`返回子字符串位置,`includes`检查是否包含子字符串。KMP是高效的搜索算法,尤其适合长模式匹配。示例展示了如何在数据采集(如网页爬虫)中使用这些方法,结合代理IP进行安全搜索。代码示例中,搜索百度新闻结果并检测是否含有特定字符串。学习这些技术能提升编程效率和性能。
117 1
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
|
3月前
|
存储 JavaScript 前端开发
JavaScript——函数式编程Functor(函子)
JavaScript——函数式编程Functor(函子)
23 0
|
4月前
|
算法 JavaScript
JS 【详解】树的遍历(含深度优先遍历和广度优先遍历的算法实现)
JS 【详解】树的遍历(含深度优先遍历和广度优先遍历的算法实现)
67 0
JS 【详解】树的遍历(含深度优先遍历和广度优先遍历的算法实现)
|
4月前
|
算法 JavaScript
JS 【详解】二叉树(含二叉树的前、中、后序遍历技巧和算法实现)
JS 【详解】二叉树(含二叉树的前、中、后序遍历技巧和算法实现)
48 0
|
4月前
|
算法 JavaScript
JS 【算法】二分查找
JS 【算法】二分查找
36 0
|
4月前
|
缓存 算法 前端开发
前端 JS 经典:LRU 缓存算法
前端 JS 经典:LRU 缓存算法
94 0