1

@冒泡的马树

题库原地址: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

13.raven


冒泡的马树
194 声望14 粉丝

曾痴迷于赛博朋克世界的代码玩家一枚,