专栏声明:只求用最简单的,容易理解的方法通过,不求优化,不喜勿喷
2634. 过滤数组中的元素
题面
请你编写一个函数,该函数接受一个整数数组参数 arr 和一个过滤函数 fn,并返回一个过滤后元素数量较少或元素数量相等的新数组。
返回的数组应该只包含通过过滤函数 fn(arr[i], i) 计算后为真值的元素。
请你在不使用内置函数 Array.filter 的前提下解决该问题。
知识点:
filter 、数组
思路
手写 filter 函数,创建一个数组作为返回值,对于我们传入的数组,根据我们传入的 fn 函数返回 true 或者 false 判断要不要将它放入我们的返回数组即可
代码
var filter = function (arr, fn) {
let re = [];
for (var i = 0; i < arr.length; i++) {
if(fn(arr[i],i)){
re.push(arr[i]);
}
}
return re;
};
2635. 转换数组中的每个元素
题面
编写一个函数,这个函数接收一个整数数组 arr 和一个映射函数 fn ,通过该映射函数返回一个新的数组。
返回数组的创建语句应为 returnedArray[i] = fn(arr[i], i) 。
请你在不使用内置方法 Array.map 的前提下解决这个问题。
知识点:
数组、map
思路
手写 map 函数,创建一个数组作为返回值,对于我们传入的数组,根据我们传入的 fn 函数返回处理后的结果,放入我们的返回数组即可
代码
var map = function(arr, fn) {
let re = [];
for(var i = 0;i<arr.length;i++){
re.push(fn(arr[i],i));
}
return re;
};
2636. Promise 对象池
题面
请你编写一个异步函数 promisePool ,它接收一个异步函数数组 functions 和 池限制 n。它应该返回一个 promise 对象,当所有输入函数都执行完毕后,promise 对象就执行完毕。
池限制 定义是一次可以挂起的最多 promise 对象的数量。promisePool 应该开始执行尽可能多的函数,并在旧的 promise 执行完毕后继续执行新函数。promisePool 应该先执行 functions[i],再执行 functions[i + 1],然后执行 functions[i + 2],等等。当最后一个 promise 执行完毕时,promisePool 也应该执行完毕。
例如,如果 n = 1 , promisePool 在序列中每次执行一个函数。然而,如果 n = 2 ,它首先执行两个函数。当两个函数中的任何一个执行完毕后,再执行第三个函数(如果它是可用的),依此类推,直到没有函数要执行为止。
你可以假设所有的 functions 都不会被拒绝。对于 promisePool 来说,返回一个可以解析任何值的 promise 都是可以接受的。
知识点:
promise 、set
思路
我们使用一个 set 来存储我们的 promise 对象,对于我们的每一个 promise 对象,我们给它一个回调函数,在他执行完毕后从我们的 set 里面删除我们的 promise 对象。
我们遍历我们需要运行的 promise ,当我们的 set 中的对象数量到达超过限制,我们使用 Promise.race 来调用我们的整个 set 直到我们的运行最快的 promise 运行结束,再继续我们的循环放入下一个元素,直到我们的放入所有的元素,我们调用 Promise.all 执行我们的 promise 池中的所有元素即可
代码
var promisePool = async function (functions, n) {
let q = new Set();
for (var i = 0; i < functions.length; i++) {
let p = functions[i]().then((res) => {
q.delete(p);
})
q.add(p);
if (q.size >= n) {
await Promise.race(q);
}
}
await Promise.all(q);
};
/**
* const sleep = (t) => new Promise(res => setTimeout(res, t));
* promisePool([() => sleep(500), () => sleep(400)], 1)
* .then(console.log) // After 900ms
*/
2637. 有时间限制的 Promise 对象
题面
请你编写一个函数,它接收一个异步函数 fn 和一个以毫秒为单位的时间 t。它应根据限时函数返回一个有 限时 效果的函数。
限时函数是与原函数相同的函数,除非它需要 t 毫秒以上的时间来完成。如果出现了这种情况,请你返回 “Time Limit Exceeded” 拒绝这次函数的调用。注意,它应该返回一个字符串拒绝,而不是一个 Error 。
知识点:
promise
思路
使用 promise.race 函数,它传入一个数组代表多个 promise 对象,但是返回最快执行完的那个,我们将我们要执行的 promise 对象和我们我们用于封装超时计算的 promise 传入 promise.race ,如果超时将执行我们封装的 Promise 对象返回一个 reject 提示信息是 ‘Time Limit Exceeded’ ,否则我们将正常我们传入的 promise
代码
var timeLimit = function(fn, t) {
return async function(...args) {
return Promise.race([
fn(...args),
new Promise((res,rej) => {
setTimeout(() => {
rej('Time Limit Exceeded');
},t)
})
])
}
};
/**
* const limited = timeLimit((t) => new Promise(res => setTimeout(res, t)), 100);
* limited(150).catch(console.log) // "Time Limit Exceeded" at t=100ms
*/
2648. 生成斐波那契数列
题面
请你编写一个生成器函数,并返回一个可以生成 斐波那契数列 的生成器对象。
斐波那契数列 的递推公式为 Xn = Xn-1 + Xn-2 。
这个数列的前几个数字是 0, 1, 1, 2, 3, 5, 8, 13 。
知识点:
js 的生成器
思路
利用 es6 的特性 —— 生成器,生成器事实上是一种特殊的迭代器,它可以让我们更加灵活的控制函数什么时候继续执行、暂停执行。
首先,生成器函数需要在function的后面加一个符号:*;
其次,生成器函数可以通过 yield 关键字来控制函数的执行流程;
生成器可以在 yield 关键字中暂停,通过调用生成器的 next 函数可以继续我们的函数,同时 yield 关键字可以返回值作为我们 next 函数返回值。
根据上述定义,我们可以很容易得到这题的解法,斐波那契数列的前两个值是 0 和 1,之后的每一个值是值是前两个值的和,那么我们先设置两个 yield 返回我们的前两个值,之后循环调用我们的函数返回前两个值的和,并且更新前两个值即可
代码
var fibGenerator = function*() {
let a = 0
let b = 1
yield a
yield b
while (true) {
c = a + b
yield c
a = b
b = c
}
};
/**
* const gen = fibGenerator();
* gen.next().value; // 0
* gen.next().value; // 1
*/
2649. 嵌套数组生成器
题面
现给定一个整数的 多维数组 ,请你返回一个生成器对象,按照 中序遍历 的顺序逐个生成整数。
多维数组 是一个递归数据结构,包含整数和其他 多维数组。
中序遍历 是从左到右遍历每个数组,在遇到任何整数时生成它,遇到任何数组时递归应用 中序遍历 。
知识点:
中序遍历、递归、生成器
思路
这题还是利用生成器,这里给出题目的中序遍历的定义,遇到任何整数时生成它,遇到任何数组时递归应用中序遍历 ,我们对着模拟即可,遍历我们的数组,如果遇到 number 类型的数据,我们调用 yield 来返回它,否则我们调用 yield 递归执行我们的函数,这个 yield 返回的也是一个生成器对象,它会递归相应我们的 next 函数直到返回一个数值
代码
var inorderTraversal = function* (arr) {
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] == "number") {
yield arr[i]
} else {
yield* inorderTraversal(arr[i]);
}
}
};
/**
* const gen = inorderTraversal([1, [2, 3]]);
* gen.next().value; // 1
* gen.next().value; // 2
* gen.next().value; // 3
*/