js
包装数组
题目
创建一个名为 ArrayWrapper 的类,它在其构造函数中接受一个整数数组作为参数。该类应具有以下两个特性:
当使用 + 运算符将两个该类的实例相加时,结果值为两个数组中所有元素的总和。
当在实例上调用 String() 函数时,它将返回一个由逗号分隔的括在方括号中的字符串。例如,[1,2,3]
示例 1:
输入:nums = [[1,2],[3,4]], operation = "Add"
输出:10
解释:
const obj1 = new ArrayWrapper([1,2]);
const obj2 = new ArrayWrapper([3,4]);
obj1 + obj2; // 10
示例 2:
输入:nums = [[23,98,42,70]], operation = "String"
输出:"[23,98,42,70]"
解释:
const obj = new ArrayWrapper([23,98,42,70]);
String(obj); // "[23,98,42,70]"
示例 3:
输入:nums = [[],[]], operation = "Add"
输出:0
解释:
const obj1 = new ArrayWrapper([]);
const obj2 = new ArrayWrapper([]);
obj1 + obj2; // 0代码
/**
* @param {number[]} nums
* @return {void}
*/
var ArrayWrapper = function (nums) {
this.nums = nums;
};
/**
* @return {number}
*/
ArrayWrapper.prototype.valueOf = function () {
return this.nums.reduce((acc, cur) => acc + cur, 0);
}
/**
* @return {string}
*/
ArrayWrapper.prototype.toString = function () {
return `[${this.nums.join(',')}]`;
}题解
构造函数存储数组
在 ArrayWrapper 构造函数里,接收一个数组 nums 作为参数,并将其存储在实例的 this.nums 属性中。这样,每个 ArrayWrapper 实例对象都能持有自己的数组数据。
valueOf 方法计算数组元素总和
valueOf 方法定义在 ArrayWrapper.prototype 上,使用 reduce 方法对 this.nums 数组中的所有元素进行累加。 reduce 方法的第二个参数 0 是累加器的初始值,当数组为空时,最终返回 0 。
toString 方法拼接数组元素
toString 方法定义在 ArrayWrapper.prototype 上,使用 join 方法将 this.nums 数组中的所有元素以 , 为间隔进行拼接,并在最终值两侧添加中括号进行包围,从而实现字符串类型转换。
执行 obj1 + obj2 的过程
当执行 obj1 + obj2 操作时,JavaScript 会尝试将 obj1 和 obj2 转换为原始值(Primitive Value)。由于 ArrayWrapper 实例对象本身不是原始值,JavaScript 会调用它们的 valueOf 方法。
执行 String(obj1) 的过程
当执行 String(obj1) 操作时,JavaScript 会调用元素的 toString 方法,因 obj1 为 ArrayWrapper 的实例对象,从而继承了 ArrayWrapper 的 toString 方法,所以调用的实则时 ArrayWrapper 的 toString 方法,从而得到 "[1,2]"。
对于 obj1 ,调用 obj1.valueOf() 会计算 [1, 2] 数组元素的总和,即 1 + 2 = 3 。
对于 obj2 ,调用 obj2.valueOf() 会计算 [3, 4] 数组元素的总和,即 3 + 4 = 7 。
最后将这两个结果相加, 3 + 7 = 10 ,得到最终的计算结果
分块数组
题目
给定一个数组 arr 和一个块大小 size ,返回一个 分块 的数组。
分块 的数组包含了 arr 中的原始元素,但是每个子数组的长度都是 size 。如果 arr.length 不能被 size 整除,那么最后一个子数组的长度可能小于 size 。
你可以假设该数组是 JSON.parse 的输出结果。换句话说,它是有效的JSON。
请你在不使用 lodash 的函数 _.chunk 的情况下解决这个问题。
示例 1:
输入:arr = [1,2,3,4,5], size = 1
输出:[[1],[2],[3],[4],[5]]
解释:数组 arr 被分割成了每个只有一个元素的子数组。
示例 2:
输入:arr = [1,9,6,3,2], size = 3
输出:[[1,9,6],[3,2]]
解释:数组 arr 被分割成了每个有三个元素的子数组。然而,第二个子数组只有两个元素。
示例 3:
输入:arr = [8,5,3,2,6], size = 6
输出:[[8,5,3,2,6]]
解释:size 大于 arr.length ,因此所有元素都在第一个子数组中。
示例 4:
输入:arr = [], size = 1
输出:[]
解释:没有元素需要分块,因此返回一个空数组。代码
/**
* @param {Array} arr
* @param {number} size
* @return {Array}
*/
var chunk = function (arr, size) {
// 如果数组为空,直接返回空数组
if (arr.length === 0) {
return [];
}
let newArr = [];
for (let i = 0; i < arr.length; i += size) {
// 截取从 i 到 i + size 的元素
newArr.push(arr.slice(i, i + size));
}
return newArr;
};根据ID合并两个不同的数组
题目
现给定两个数组 arr1 和 arr2 ,返回一个新的数组 joinedArray 。两个输入数组中的每个对象都包含一个 id 字段。
joinedArray 是一个通过 id 将 arr1 和 arr2 连接而成的数组。joinedArray 的长度应为唯一值 id 的长度。返回的数组应按 id 升序 排序。
如果一个 id 存在于一个数组中但不存在于另一个数组中,则该对象应包含在结果数组中且不进行修改。
如果两个对象共享一个 id ,则它们的属性应进行合并:
如果一个键只存在于一个对象中,则该键值对应该包含在对象中。
如果一个键在两个对象中都包含,则
arr2中的值应覆盖arr1中的值。
示例 1:
输入:
arr1 = [
{"id": 1, "x": 1},
{"id": 2, "x": 9}
],
arr2 = [
{"id": 3, "x": 5}
]
输出:
[
{"id": 1, "x": 1},
{"id": 2, "x": 9},
{"id": 3, "x": 5}
]
解释:没有共同的 id,因此将 arr1 与 arr2 简单地连接起来。
示例 2:
输入:
arr1 = [
{"id": 1, "x": 2, "y": 3},
{"id": 2, "x": 3, "y": 6}
],
arr2 = [
{"id": 2, "x": 10, "y": 20},
{"id": 3, "x": 0, "y": 0}
]
输出:
[
{"id": 1, "x": 2, "y": 3},
{"id": 2, "x": 10, "y": 20},
{"id": 3, "x": 0, "y": 0}
]
解释:id 为 1 和 id 为 3 的对象在结果数组中保持不变。id 为 2 的两个对象合并在一起。arr2 中的键覆盖 arr1 中的值。
示例 3:
输入:
arr1 = [
{"id": 1, "b": {"b": 94},"v": [4, 3], "y": 48}
]
arr2 = [
{"id": 1, "b": {"c": 84}, "v": [1, 3]}
]
输出: [
{"id": 1, "b": {"c": 84}, "v": [1, 3], "y": 48}
]
解释:具有 id 为 1 的对象合并在一起。对于键 "b" 和 "v" ,使用 arr2 中的值。由于键 "y" 只存在于 arr1 中,因此取 arr1 的值。代码
/**
* @param {Array} arr1 - 第一个包含具有 id 字段对象的数组。
* @param {Array} arr2 - 第二个包含具有 id 字段对象的数组。
* @return {Array} - 合并后的数组,按 id 升序排序。
*/
var join = function (arr1, arr2) {
// 创建一个空对象 idMap,用于存储合并后的对象,键为 id
const idMap = {}
// 遍历 arr1 中的每个对象
for (let obj of arr1) {
// 将 arr1 中的对象添加到 idMap 中,键为对象的 id
idMap[obj.id] = {
...obj
}
}
// 遍历 arr2 中的每个对象
for (let obj of arr2) {
// 如果 idMap 中已经存在该 id
if (idMap[obj.id]) {
// 合并 idMap 中该 id 对应的对象和当前 arr2 中的对象,arr2 中的值会覆盖 arr1 中的值
idMap[obj.id] = {
...idMap[obj.id],
...obj
}
} else {
// 如果 idMap 中不存在该 id,直接将 arr2 中的对象添加到 idMap 中
idMap[obj.id] = {
...obj
}
}
}
// 将 idMap 中的所有值转换为数组,并按 id 升序排序
const joinedArray = Object.values(idMap).sort((a, b) => a.id - b.id)
// 返回合并并排序后的数组
return joinedArray;
};睡眠函数
题目
请你编写一个异步函数,它接收一个正整数参数 millis ,并休眠 millis 毫秒。要求此函数可以解析任何值。
示例 1:
输入:millis = 100
输出:100
解释:
在 100ms 后此异步函数执行完时返回一个 Promise 对象
let t = Date.now();
sleep(100).then(() => {
console.log(Date.now() - t); // 100
});
示例 2:
输入:millis = 200
输出:200
解释:在 200ms 后函数执行完时返回一个 Promise 对象代码
/**
* @param {number} millis
* @return {Promise}
*/
async function sleep(millis) {
return new Promise(reslove=>{
setTimeout(()=>{
reslove();
},millis)
})
}
/**
* let t = Date.now()
* sleep(100).then(() => console.log(Date.now() - t)) // 100
*/蜗牛排序
题目
请你编写一段代码为所有数组实现 snail(rowsCount,colsCount) 方法,该方法将 1D 数组转换为以蜗牛排序的模式的 2D 数组。无效的输入值应该输出一个空数组。当 rowsCount * colsCount !==nums.length 时。这个输入被认为是无效的。
蜗牛排序从左上角的单元格开始,从当前数组的第一个值开始。然后,它从上到下遍历第一列,接着移动到右边的下一列,并从下到上遍历它。将这种模式持续下去,每列交替变换遍历方向,直到覆盖整个数组。例如,当给定输入数组 [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15] ,当 rowsCount = 5 且 colsCount = 4 时,需要输出矩阵如下图所示。注意,矩阵沿箭头方向对应于原数组中数字的顺序

示例 1:
输入:
nums = [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15]
rowsCount = 5
colsCount = 4
输出:
[
[19,17,16,15],
[10,1,14,4],
[3,2,12,20],
[7,5,18,11],
[9,8,6,13]
]
示例 2:
输入:
nums = [1,2,3,4]
rowsCount = 1
colsCount = 4
输出:[[1, 2, 3, 4]]
示例 3:
输入:
nums = [1,3]
rowsCount = 2
colsCount = 2
输出:[]
Explanation: 2 * 2 = 4, 且原数组 [1,3] 的长度为 2; 所以,输入是无效的。代码
/**
* @param {number} rowsCount
* @param {number} colsCount
* @return {Array<Array<number>>}
*/
Array.prototype.snail = function (rowsCount, colsCount) {
if (this.length !== rowsCount * colsCount) {
return [];
}
const result = Array.from({
length: rowsCount
}, () => Array(colsCount).fill(0));
let index = 0;
for (let col = 0; col < colsCount; col++) {
if (col % 2 === 0) {
for (let row = 0; row < rowsCount; row++) {
result[row][col] = this[index++];
}
} else {
for (let row = rowsCount - 1; row >= 0; row--) {
result[row][col] = this[index++];
}
}
}
return result;
};