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

5次阅读

共计 19405 个字符,预计需要花费 49 分钟才能阅读完成。

@冒泡的马树

题库原地址:http://csbin.io/functional

高阶函数

挑战 1

问题:

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

题解:

// 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 函数,作用为承受一个参数并将参数与“s” 拼接。

题解:

// 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 函数,其承受两个参数:

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

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

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

题解:

// 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 函数无返回值。

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

题解:

// 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

问题:

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

题解:

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

挑战 6

问题:

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

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 并最终返回。

题解:

// 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 函数,作用为比拟输出进来的多组数组并返回一个蕴含数组间独特元素的新数组。处分:应用 reduce!

题解:

// 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 函数,作用为比拟输出进来的多组数组并返回一个蕴含输出数组中所有元素的新数组。如果存在反复元素,则新数组中仅保留一个,另外需保留新数组的元素程序为从第一个输出数组的第一个元素开始。处分:应用 reduce!

题解:

// 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 会应用回调函数测试第一个数组的每一个元素以确认其输入是否匹配于第二个数组内雷同下标的元素。如果匹配,第一个数组内的这个元素会成为所创建对象的键,而第二个数组内的雷同下标元素则会成为对应的值。

题解:

// 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 会返回一个特定对象,该对象的键为第一个数组的值,键对应的值则是将键依序传入第二个数组的回调函数中失去的返回值组成的新数组。

题解:

// 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 会返回一个布尔值,从而表明运行第一个回调函数于输出值,再将失去的返回值输出到第二个回调函数中运行,失去的后果与逆序操作是否雷同(即运行输出值于第二个回调函数,失去的返回值再输出到第一个回调函数中)。

题解:

// Challenge 11
const commutative = (func1, func2, value) => {if(func1(func2(value)) === func2(func1(value))){return true;} else {return false;}
};

/*** 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 函数会返回特定对象。此特定对象所蕴含的属性为输出对象中值与其对应键传入回调函数失去的返回值统一的键值对。

题解:

// 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 函数,承受参数为一个由函数组成的数组和一个值。数组中的函数的返回值皆为 true 或 false。rating 会返回一个表明将输出值运行于数组中的函数会返回 true 的百分比数。

题解:

// 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 会返回这个最终输入值。

题解:

// 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 会返回输出对象中运行输出值后失去最高值的函数所对应的键。

题解:

// 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 函数,用于创立和返回函数。当被创立的函数被调用时,它会打印“hello”。

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

题解:

// Challenge 1
const createFunction = () => {const innerFunction = () => {console.log('hello');
    }
    return innerFunction;
};

// UNCOMMENT THESE TO TEST YOUR WORK!
const function1 = createFunction();
function1();

挑战 2

问题:

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

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');

题解:

// 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 函数失去的输入值。

代码:

// 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 函数,其会返回一个承受一个输出值作为参数并与 x 相加的函数。

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

题解:

// 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 函数,承受参数为一个回调函数并返回一个特定函数。当特定函数被第一次调用时,其会调用回调函数并返回输入值。如果其不是被第一次调用,则特定函数仅仅返回第一次调用时失去的回调函数返回值,而不是再次运行回调函数。

题解:

// 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 函数,承受一个数字 n 和一个回调函数作为参数。回调函数须要在通过 after 构建的函数运行第 n 次时才被运行。

题解:

// 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 函数,作用为承受一个回调函数作为第一个参数,一个数值 n(单位为毫秒)作为第二个参数,返回一个特定函数。delay 构建的特定函数被调用后,须经 n 毫秒后才运行回调函数。任何其余赋给特定函数的参数会在 n 毫秒后被回调函数应用。提醒:钻研 setTimeout();

题解:

// 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 函数,作用为承受一个数值参数(假如为 n)并返回一个特定函数。此特定函数不承受输出参数,而且会在前 n - 1 次调用时返回字符串“click“,在第 n 次调用时则返回字符串”bang“,n 次当前再调用皆返回字符串”reload to play again”。

题解:

// Challenge 8
const russianRoulette = (num) => {
    let counter = num;
  const innerFunction = () => {
    counter--;
    if(counter>0) {return "click";} else if(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";} else if(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 创立的特定函数被输出数值参数的形式调用时,返回值为所有已经被输出到特定函数的数值参数的平均值(反复数值视为别离的数值)。当特定函数被无参数的形式调用时,返回以后的平均值。如果特定函数在无参数形式调用时未曾被输出数值参数的形式调用过,则返回 0。

题解:

// 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 函数,承受参数为一个二维数组(其中第二维数组仅含两个元素),返回一个接管回调函数作为参数的特定函数。当二维数组的每一个子数组的第一个元素输出到回调函数时都产生与第二个元素雷同的返回值时,特定函数返回 ture,否则特定函数返回 false。

题解:

// Challenge 10
const makeFuncTester = (arrOfTests) => {const firstLayerArray = [];
  for(let i = 0; i<arrOfTests.length; i++){let secondLayerArray = [];
    for(let j = 0; j<arrOfTests[i].length; j++){secondLayerArray.push(arrOfTests[i][j]);
    }
    firstLayerArray.push(secondLayerArray);
  }
  const innerFunction = (callback) => {for(let i=0; i<firstLayerArray.length; i++){if(callback(firstLayerArray[i][0]) !== firstLayerArray[i][1]){return false;}
    }
    return true;
  }
  return innerFunction;
};

/*** Uncomment these to check your work! ***/
const capLastTestCases = [];
capLastTestCases.push(['hello', 'hellO']);
capLastTestCases.push(['goodbye', 'goodbyE']);
capLastTestCases.push(['howdy', 'howdY']);
const shouldCapitalizeLast = makeFuncTester(capLastTestCases);
const capLastAttempt1 = str => str.toUpperCase();
const capLastAttempt2 = str => str.slice(0, -1) + str.slice(-1).toUpperCase();
console.log(shouldCapitalizeLast(capLastAttempt1)); // should log: false
console.log(shouldCapitalizeLast(capLastAttempt2)); // should log: true

挑战 11

问题:

构建 makeHistory 函数,承受一个数值参数 n(充当限定值)并返回一个特定函数(承受字符串作为参数)。特定函数会存储限定个数为 n 的最近输出到此特定函数中的字符串参数历史(每次调用存储一次)。每次一个字符串被输出到特定函数中,特定函数会返回拼接“done”于此字符串后的新字符串(空格作为距离)。然而,如果输出字符串为“undo”,特定函数会删除字符串参数历史中的最近字符串值,返回拼接“undone”于此最近字符串后的新字符串(空格作为距离)。如果输出字符串“undo”时特定函数中的字符串参数历史已为空,那么特定函数会返回字符串“nothing to undo”。

题解:

// Challenge 11
const makeHistory = (limit) => {
    const limitNumber = limit; 
  let parameterStack = [];
  const innerFunction = (stringElement) => {if(stringElement === "undo"){if(parameterStack.length == 0) {return "nothing to undo";} else{return `${parameterStack.pop()} undone`;
      }
    } else{parameterStack.push(stringElement);
      if(parameterStack.length > limit){parameterStack = parameterStack.slice(-limit);
      }
      return `${stringElement} done`;
    }
  }
  return innerFunction;
};

/*** Uncomment these to check your work! ***/
const myActions = makeHistory(2);
console.log(myActions('jump')); // should log: 'jump done'
console.log(myActions('undo')); // should log: 'jump undone'
console.log(myActions('walk')); // should log: 'walk done'
console.log(myActions('code')); // should log: 'code done'
console.log(myActions('pose')); // should log: 'pose done'
console.log(myActions('undo')); // should log: 'pose undone'
console.log(myActions('undo')); // should log: 'code undone'
console.log(myActions('undo')); // should log: 'nothing to undo'

挑战 12

问题:

仔细观察测试代码如果你须要帮忙来了解上面的算法形容。

构建 blackjack 函数,承受参数为一个数组(元素皆为从 1 到 11 的数值),返回一个 DEALER 函数。DEALER 函数会承受两个参数(皆为数值),而后返回一个另外的 PLAYER 函数。

在第一次调用 PLAYER 函数时,它会返回输出 DEALER 函数中的两个数值参数之和。

在第二次调用 PLAYER 函数时,它会返回下列两种状况中的一种:

  1. 输出 blackjack 函数的数值型数组的第一个数值加上输出 DEALER 函数中的两个数值参数之和失去的和,如果和小于等于 21,返回此和;
  2. 如果和大于 21,返回字符串“bust”。

如果第二次调用 PLAYER 函数时已返回 ”bust”,则接下来 PLAYER 函数的每次调用皆会返回字符串“you are done!”(不过不同于“bust”,输入”you are done!“时不会应用数值型数组中的数值 )。如果第二次调用 PLAYER 函数时并未返回”bust“,则接下来调用 PLAYER 函数时会返回下列两种状况中的一种:

  1. 最近一次的和值加上数值型数组的下一个数值元素,如果这个求和后果小于等于 21 的话,返回此和;
  2. 返回“bust”如果求和后果大于 21。

再次申明,如果其返回 ”bust”,则接下来 PLAYER 函数的每次调用皆会返回字符串“you are done!”,否则,PLAYER 函数会持续应用最近一次和值与数值型数组的下一个数值元素求和,始终上来。

你能够假如给定的数值型数组有足够多的数值元素从而会在用完数组元素之前失去“bust”。

题解:

// Challenge 12
const blackjack = (array) => {const dealer = (num1, num2) => {
    let first = true;
    let bust = false; 
    let sum = num1 + num2; 
    const player = () => {if(first) {
        first = false; 
        return sum; 
      }
      if (bust) {return "you are done!";}
      if(sum + array[0] <= 21) {sum += array.shift();
        return sum; 
      } else {array.shift();
        bust = true;
        return "bust";
      }
    }
    return player;
  }
  return dealer;
};

/*** Uncomment these to check your work! ***/

/*** DEALER ***/
const deal = blackjack([2, 6, 1, 7, 11, 4, 6, 3, 9, 8, 9, 3, 10, 4, 5, 3, 7, 4, 9, 6, 10, 11]);

/*** PLAYER 1 ***/
const i_like_to_live_dangerously = deal(4, 5);
console.log(i_like_to_live_dangerously()); // should log: 9
console.log(i_like_to_live_dangerously()); // should log: 11
console.log(i_like_to_live_dangerously()); // should log: 17
console.log(i_like_to_live_dangerously()); // should log: 18
console.log(i_like_to_live_dangerously()); // should log: 'bust'
console.log(i_like_to_live_dangerously()); // should log: 'you are done!'
console.log(i_like_to_live_dangerously()); // should log: 'you are done!'

/*** BELOW LINES ARE FOR THE BONUS ***/

/*** PLAYER 2 ***/
const i_TOO_like_to_live_dangerously = deal(2, 2);
console.log(i_TOO_like_to_live_dangerously()); // should log: 4
console.log(i_TOO_like_to_live_dangerously()); // should log: 15
console.log(i_TOO_like_to_live_dangerously()); // should log: 19
console.log(i_TOO_like_to_live_dangerously()); // should log: 'bust'
console.log(i_TOO_like_to_live_dangerously()); // should log: 'you are done!
console.log(i_TOO_like_to_live_dangerously()); // should log: 'you are done!

/*** PLAYER 3 ***/
const i_ALSO_like_to_live_dangerously = deal(3, 7);
console.log(i_ALSO_like_to_live_dangerously()); // should log: 10
console.log(i_ALSO_like_to_live_dangerously()); // should log: 13
console.log(i_ALSO_like_to_live_dangerously()); // should log: 'bust'
console.log(i_ALSO_like_to_live_dangerously()); // should log: 'you are done!
console.log(i_ALSO_like_to_live_dangerously()); // should log: 'you are done!

额定挑战

挑战 1

问题:

构建 functionValidator 函数,承受参数为一个函数型数组和两个不同的数值(称之为 input 和 output)。此函数应返回一个特定数组,此特定数组仅蕴含输出函数数组中调用 input 时会返回 output 的函数。应用 reduce!

题解:

// Challenge 1
const functionValidator = (funcArr, input, output) => {return funcArr.reduce((acc, curr) => {if(curr(input) === output) {acc.push(curr);
    }
    return acc;
  }, [])
}

const addFive = num => num + 5;
const multiplyByTwo = num => num * 2;
const subtractOne = num => num - 1;
const fnArr = [addFive, multiplyByTwo, subtractOne];

console.log(functionValidator(fnArr, 5, 10)) // should log [num => num + 5, num => num * 2]

挑战 2

问题:

构建 allClear 函数,承受参数为一个由验证型函数(返回布尔值)组成的数组和一个数值。allClear 中应应用 reduce 来返回一个布尔值从而表明输出数值是否能够通过输出函数数组中的所有函数(即皆返回 true)。

题解:

// Challenge 2
const allClear = (funcArr, value) => {
    // // Solution 1: 
    // let indicator = false;
    // indicator = funcArr.reduce((acc, curr) => {// if(acc == true && curr(value) === true) {
    // acc = true;
    // } else {
    // acc = false;
    // }
    // return acc;
    // }, true)
    // return indicator; 
  
  // Solution 2: 
  return funcArr.reduce((acc, curr) => {if(acc) return curr(value);
    return acc;
  }, true)
}

const isOdd = num => num % 2 === 1;
const isPositive = num => num > 0;
const multipleOfFive = num => num % 5 === 0;
const numFnArr = [isOdd, isPositive, multipleOfFive];
console.log(allClear(numFnArr, 25)) // should log true 
console.log(allClear(numFnArr, -25)) // should log false
 

挑战 3

问题:

构建 numSelectString 函数,承受参数为数值型数组,返回一个字符串。此函数应应用 filter、sort 和 reduce 来返回一个仅蕴含输出数组中的奇数的字符串,以半角逗号隔开,且升序。

题解:

// Challenge 3
const numSelectString = (numArr) => {
    // // Solution 1: 
    // let strNumArr = "";
    // let numOddArr = [];
    // numOddArr = numArr.reduce((acc, curr) => {// if(curr % 2 == 1){// acc.push(curr);
    // }
    // return acc;
    // }, [])
    // numOddArr.sort((a,b) => a-b);
    // numOddArr.forEach((el) => {// if(strNumArr == "") {// strNumArr += el.toString();
    // } else {// strNumArr += "," + el.toString();
    // }
    // })
    // return strNumArr;
  
  // Solution 2: 
  return numArr.sort((a,b) => a - b)
          .filter(num => num % 2 === 1)
          .reduce((acc, curr) => {return acc + "," + curr;})
}

const numbers = [17, 34, 3, 12]
console.log(numSelectString(numbers)) // should log "3, 17"

挑战 4

问题:

构建 movieSelector 函数,承受参数为一个对象型数组(对象为电影信息,含 id、题目和分数)。请在 movieSeletor 函数内链式调用 map、filter 和 reduce,返回一个仅蕴含分数大于 5 的电影题目的数组。电影题目应全为大写。

题解:

// Challenge 4
const movieSelector = (moviesArr) => {return moviesArr.map( el => { return {"title": el.title.toUpperCase(), "score": el.score}})
          .filter(el => el.score > 5)
            .reduce((acc, curr) => {acc.push(curr.title);
            return acc;
      }, [])
}

const movies = [{ id: 1, title: "Pan's Labyrinth", score: 9}, {id: 37, title:"Manos: The Hands of Fate", score: 2}, {title:"Air Bud", score: 5}, {title:"Hackers", score: 7} ]
console.log(movieSelector(movies)) // should log ["PAN'S LABYRINTH","HACKERS"]

挑战 5

问题:

构建 curriedAddThreeNums 函数,共承受 3 个数值作为参数,每次调用输出一个数值,共调用三次,如下:

curriedAddThreeNums(1)(3)(7) //should return 10

题解:

// Challenge 5
const curriedAddThreeNums = (num1) => {return (num2) => {return (num3) =>{return num1 + num2 + num3;}
  }
}

console.log(curriedAddThreeNums(3)(-1)(1)); // should log 3

挑战 6

问题:

局部借助你在挑战 5 中创立的 curriedAddThreeNums 函数来构建 curriedAddTwoNumsToFive 函数,此函数承受两个数组参数,每次调用输出一个数值,共两次,最终求得两个数值与 5 的和,如下:

curriedAddTwoNumsToFive(6)(7) //should return 18

题解:

// Challenge 6
const curriedAddTwoNumsToFive = curriedAddThreeNums(5);

console.log(curriedAddTwoNumsToFive(6)(7)) // should log 18

正文完
 0