字节跳动面试题目:利用已知函数 add
实现 asyncSum
。
function add (a, b, callback) {
callback(a + b)
}
async function asyncSum(...args) {
// 具体实现
}
// await asyncSum(1, 2, 3, 4, 5) 的结果应当为 1 + 2 + 3 + 4+ 5 = 15
解题思路:
[1, 2, 3, 4, 5] // 传参
[[1, 2], [3, 4], [5, 0]] // 分组
[3, 7, 5] // 各组求和
[[3, 7], [5, 0]] // 继续分组
[10, 5] // 继续各组求和
[[10, 5]] // 继续分组
[15] // 求和
首先,实现分组函数,将参数分成 2 个一组。
function chunk(arr) {
let ret = []
for (let i = 0; i < arr.length; i += 2) {
ret.push([arr[i], arr[i + 1] ? arr[i + 1] : 0])
}
return ret
}
chunk([1, 2, 3, 4, 5]) // [[1, 2], [3, 4], [5, 0]]
然后,实现 sum 函数对分组的数字依次求和。由于需要强依赖 add
函数,首先将 add
函数 promisify
。
function add (a, b, callback) {
callback(a + b)
}
function asyncAdd(a, b) {
return new Promise(resolve => add(a, b, sum => resolve(sum)))
}
实现 sum
函数。
function sum(nums) {
return Promise.all(chunk(nums).map(([a, b]) => asyncAdd(a, b)))
}
// await sum([1, 2, 3, 4, 5]) 结果 [3, 7, 5]
至此,可以看出数字长度在缩减,所以只需要继续拆分数组调用 sum
函数直到数字长度为 1 即为最终求和。
async function asyncSum(...args) {
let ret = await sum(args)
while (ret.length > 1) {
ret = await sum(ret)
}
return ret[0]
}
完整实现。
function chunk(arr) {
let ret = []
for (let i = 0; i < arr.length; i += 2) {
ret.push([arr[i], arr[i + 1] ? arr[i + 1] : 0])
}
return ret
}
function add (a, b, callback) {
callback(a + b)
}
function asyncAdd(a, b) {
return new Promise(resolve => add(a, b, sum => resolve(sum)))
}
function sum(nums) {
return Promise.all(chunk(nums).map(([a, b]) => asyncAdd(a, b)))
}
async function asyncSum(...args) {
let ret = await sum(args)
while (ret.length > 1) {
ret = await sum(ret)
}
return ret[0]
}
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.