leetcode — JavaScript专题(七):精简对象、执行可取消的延迟函数、并行执行异步函数、根据 ID 合并两个数组、添加两个 Promise 对象、排序方式

专栏声明:只求用最简单的,容易理解的方法通过,不求优化,不喜勿喷

2705. 精简对象

题面

现给定一个对象或数组 obj,返回一个 精简对象 。精简对象 与原始对象相同,只是将包含 假 值的键移除。该操作适用于对象及其嵌套对象。数组被视为索引作为键的对象。当 Boolean(value) 返回 false 时,值被视为 假 值。
你可以假设 obj 是 JSON.parse 的输出结果。换句话说,它是有效的 JSON。

知识点:

深度优先遍历

思路

典型的分类判断 + 递归题目,前面也出现不少了,我们传入的是一个对象或数组所以我们先要用 Array.isArray 判定它是数组还是对象:

  • 如果是数组,我们递归其中的每一项,如果不是 false ,把它放到返回的数组中。
  • 如果是对象,我们递归其中的每一个 key,如果不是 false ,我们把这个键值对放到返回的对象中。
    因为我们递归的时候会把不是 数组和对象 的值传入,所以我们判断,如果传入的值不是 object 类型或是 null (因为 null 也会被判定为 object 类型),直接返回(它的判定会在上一级中处理)
代码
var compactObject = function(obj) {

    if (obj == null || typeof obj !== 'object') {
        return obj;
    }
    if (Array.isArray(obj)) {
        const res = [];
        for (let it of obj) {
            const val = compactObject(it);
            if (val) res.push(val);
        }
        return res;
    }
    const res = {};
    const keys = Object.keys(obj);
    for (let key of keys) {
        const val = compactObject(obj[key]);
        if (val) res[key] = val;
    }
    return res;
};

2715. 执行可取消的延迟函数

题面

现给定一个函数 fn ,一个参数数组 args 和一个以毫秒为单位的超时时间 t ,返回一个取消函数 cancelFn 。
在经过 t 毫秒的延迟后,除非 先调用 cancelFn ,否则 fn 应该以 args 作为参数被调用。并且在这种情况下,fn 不应该被调用。

知识点:

计数器,闭包

思路

一个很简单的闭包的应用,创建一个计时器,在一定延迟后执行需要的执行的函数,同时返回一个函数来取消它,这个函数清除了计时器,因为闭包的特性,我们可以用这个函数来访问函数中创建的计时器。

代码
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    let timer = setTimeout(() => {
        fn(...args)
    },t)
    return () => { clearTimeout(timer) };
};

2721. 并行执行异步函数

题面

这题也是笔者的字节跳动面试手写题(实现一个 promise.all)
给定一个异步函数数组 functions,返回一个新的 promise 对象 promise。数组中的每个函数都不接受参数并返回一个 promise。
promise resolve 条件:
当所有从 functions 返回的 promise 都成功解析时。promise 的解析值应该是一个按照它们在 functions 中的顺序排列的 promise 的解析值数组。
promise reject 条件:
当任何从 functions 返回的 promise 被拒绝时。promise 也会被拒绝,并返回第一个拒绝的原因。
请在不使用内置的 Promise.all 函数的情况下解决。

知识点:

promise、promise.all

思路

实现一个 promise.all,这个函数 api 会在传入的所有 promise 完成后返回,我们先 new 一个 promise 作为返回值,这个 promise 的成功返回是在传入的所有 promise 执行完毕之后 ,而失败返回是在一个 promise 失败之后。
我们用一个 now 记录执行已经执行完几个了,之后遍历传入的 数组,对于每个 promise,它执行完毕后,将对应的返回值放在返回的数组执行位置,然后让 now + 1。
如果此时 now 和传入数组的长度一样,说明执行完毕了,把记录所有返回值的数组作为成功返回。
如果有任何一个传入的 promise 失败了,那么我们直接失败返回这个失败 promise 的错误信息。

代码
/**
 * @param {Array<Function>} functions
 * @return {Promise<any>}
 */
var promiseAll = async function (functions) {
    let now = 0;
    let re = new Array(functions.length);
    return new Promise((res, rej) => {
        for (let i = 0; i < functions.length; i++) {
            functions[i]().then((data) => {
                now++;
                re[i] = data
                if (now == functions.length) {
                    res(re);
                }
            },(err) => {
                rej(err);
            })
        }
    })
};
/**
 * const promise = promiseAll([() => new Promise(res => res(42))])
 * promise.then(console.log); // [42]
 */

2722. 根据 ID 合并两个数组

题面

现给定两个数组 arr1 和 arr2 ,返回一个新的数组 joinedArray 。两个输入数组中的每个对象都包含一个 id 字段。joinedArray 是一个通过 id 将 arr1 和 arr2 连接而成的数组。joinedArray 的长度应为唯一值 id 的长度。返回的数组应按 id 升序 排序。
如果一个 id 存在于一个数组中但不存在于另一个数组中,则该对象应包含在结果数组中且不进行修改。
如果两个对象共享一个 id ,则它们的属性应进行合并:
如果一个键只存在于一个对象中,则该键值对应该包含在对象中。
如果一个键在两个对象中都包含,则 arr2 中的值应覆盖 arr1 中的值。

知识点:

归并排序、对象合并

思路

双指针的思路,我们先对两个数组按照 id 的大小排序,之后从两个数组的第一位开始合并:

  • 如果两个指针指向的元素 id 相同,那么这个元素需要合并,使用 Object.assign 来实现,这个函数的逻辑是:如果一个键只存在于一个对象中,则该键值对应该包含在对象中,如果一个键在两个对象中都包含,则 arr2 中的值应覆盖 arr1 中的值,即题目的要求。
  • 如果指向的 id 不同,我们将其中 id 小的那个放入结果,继续我们的遍历
  • 当任何一个数组遍历结束,我们把论一个数组中剩余的元素放入结果数组中即可
代码
/**
 * @param {Array} arr1
 * @param {Array} arr2
 * @return {Array}
 */
var join = function (arr1, arr2) {
    arr1.sort((a, b) => a.id - b.id);
    arr2.sort((a, b) => a.id - b.id);
    let res = [];
    let j = 0;
    for (var i = 0; i < arr1.length; i++) {
        if (j == arr2.length) {
            break;
        }
        let id1 = arr1[i].id;
        if (arr2[j].id == id1) {
            res.push(Object.assign(arr1[i], arr2[j]));
            j++;
        } else if (arr2[j].id < id1) {
            res.push(arr2[j]);
            j++;
            i--;
        } else {
            res.push(arr1[i]);
        }
    }
    while (i < arr1.length) {
        res.push(arr1[i]);
        i++;
    }
    while (j < arr2.length) {
        res.push(arr2[j]);
        j++;
    }
    return res.sort((a, b) => a.id - b.id);
};

2723. 添加两个 Promise 对象

题面

给定两个 promise 对象 promise1 和 promise2,返回一个新的 promise。promise1 和 promise2 都会被解析为一个数字。返回的 Promise 应该解析为这两个数字的和。

知识点:

promise

思路

考察 promise 的基本概念。使用 promise.then 来等待两个 promise 返回,需要在一个 promise 返回后再去处理论一个 promise ,或者用 promise.all 来处理他们,在两个 promise 的返回值都拿到之后,相加返回作为新的 promise 的成功返回即可

代码
/**
 * @param {Promise} promise1
 * @param {Promise} promise2
 * @return {Promise}
 */
var addTwoPromises = async function(promise1, promise2) {
    return new Promise((res,rej) => {

        promise1.then((res1) => {
            promise2.then((res2) => {
                res(res1 + res2)
            })
        }) 
    })
};

/**
 * addTwoPromises(Promise.resolve(2), Promise.resolve(2))
 *   .then(console.log); // 4
 */

2724. 排序方式

题面

给定一个数组 arr 和一个函数 fn,返回一个排序后的数组 sortedArr。你可以假设 fn 只返回数字,并且这些数字决定了 sortedArr 的排序顺序。sortedArr 必须按照 fn 的输出值 升序 排序。

你可以假设对于给定的数组,fn 不会返回重复的数字。

知识点:

sort

思路

简单题略… 考察 sort 这个 api 的使用,它传入两个值,你可以对这两个值进行处理,然后在进行比较逻辑

代码
/**
 * @param {Array} arr
 * @param {Function} fn
 * @return {Array}
 */
var sortBy = function (arr, fn) {
   return arr.sort((a, b) => fn(a) - fn(b));
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼老萌新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值