前端笔试题
/**
* 给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。
* 返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。
* 可以不考虑输出结果的顺序。
*
* 输入:nums1 = [1,2,2,1], nums2 = [2,2]
* 输出:[2,2]
*
* 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
* 输出:[4,9]
*/
const nums1 = [1,2,2,1], nums2 = [2,2,1, 2, 2]
function intersect(nums1, nums2) {
let map = new Map(), arr = [], len1 = nums1.length, len2 = nums2.length
for (let a = 0; a < len1; a++) {
if (map.has(nums1[a])) {
map.set(nums1[a], map.get(nums1[a]) + 1)
} else {
map.set(nums1[a], 1)
}
}
for (let a = 0; a < len2; a++) {
if (map.has(nums2[a]) && map.get(nums2[a]) > 0) {
arr.push(nums2[a])
map.set(nums2[a], map.get(nums2[a]) - 1)
}
}
return arr
};
const result = intersect(nums1, nums2)
console.log(result)
/**
* 已知如下数组:var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
* 编写一个函数将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组
*/
// 方式一:
const arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
const s = new Set()
function arrHandle(arr) {
if (Array.isArray(arr)) {
arr.forEach(children => {
arrHandle(children)
})
} else {
s.add(arr)
}
}
arrHandle(arr)
const result = [...s].sort((a, b) => a - b)
console.log(result)
// 方式二:
console.log(Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b}))
/**
* 设计 LazyMan 类,实现以下功能
* LazyMan('Tony');
* // Hi I am Tony
*
* LazyMan('Tony').sleep(10).eat('lunch');
* // Hi I am Tony
* // 等待了10秒...
* // I am eating lunch
*
* LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
* // Hi I am Tony
* // I am eating lunch
* // 等待了10秒...
* // I am eating diner
*
* LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
* // Hi I am Tony
* // 等待了5秒...
* // I am eating lunch
* // I am eating dinner
* // 等待了10秒...
* // I am eating junk food
*/
// 实现
class LazyMain {
constructor(name) {
this.name = name
console.log(`Hi I am ${this.name}`)
this.callbacks = []
}
eat(food) {
// 订阅
this.callbacks.push(() => console.log(`I am eating ${food}`))
// 加入微任务在同步代码执行完毕后执行
process.nextTick(() => {
const fn = this.callbacks.shift()
fn && fn()
})
return this
}
sleep(delay) {
const newDate = Date.now()
while((Date.now() - newDate) / 1000 < delay){}
return this
}
sleepFirst(delay) {
this.sleep(delay)
// 发布
this.callbacks.forEach(fn => fn())
this.callbacks = []
return this
}
}
const lazyMain = new LazyMain('Tony')
lazyMain.eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
// 执行结果
// Hi I am Tony
// I am eating lunch
// I am eating dinner
// I am eating junk food
/**
* 模拟实现发布订阅模式
*/
class Observe {
constructor() {
this.message = {};
}
$on(type, fn) {
this.message[type]
? this.message[type].push(fn)
: (this.message[type] = [fn]);
}
$off(type, fn) {
if (!this.message[type]) return;
if (!fn) {
this.message[type] = undefined;
} else {
console.log("else");
this.message[type] = this.message[type].filter((el) => el != fn);
}
}
$emit(type) {
if (!this.message[type]) return;
this.message[type].forEach((el) => {
el();
});
}
}
const person1 = new Observe();
function handler1() {
console.log("handler1");
}
function handler2() {
console.log("handler2");
}
person1.$on("abc", handler1);
person1.$on("abc", handler2);
person1.$emit("abc");
console.log(person1.message);
// 执行结果
// handler1
// handler2
// { abc: [ [Function: handler1], [Function: handler2] ] }
/**
* 以下数据结构中,id 代表部门编号,name 是部门名称,parentId 是父部门编号,为 0 代表一级部门,
* 现在要求实现一个 convert 方法,把原始 list 转换成树形结构,parentId 为多少就挂载在该 id 的属性 children 数组下,结构如下:
* 原始 list 如下
let list =[
{id:1,name:'部门A',parentId:0},
{id:2,name:'部门B',parentId:0},
{id:3,name:'部门C',parentId:1},
{id:4,name:'部门D',parentId:1},
{id:5,name:'部门E',parentId:2},
{id:6,name:'部门F',parentId:3},
{id:7,name:'部门G',parentId:2},
{id:8,name:'部门H',parentId:4}
];
转换后的结果如下
let result = [
{
id: 1,
name: '部门A',
parentId: 0,
children: [
{
id: 3,
name: '部门C',
parentId: 1,
children: [
{
id: 6,
name: '部门F',
parentId: 3
}, {
id: 16,
name: '部门L',
parentId: 3
}
]
},
{
id: 4,
name: '部门D',
parentId: 1,
children: [
{
id: 8,
name: '部门H',
parentId: 4
}
]
}
]
},
···
];
*/
let list =[
{id:1,name:'部门A',parentId:0},
{id:2,name:'部门B',parentId:0},
{id:3,name:'部门C',parentId:1},
{id:4,name:'部门D',parentId:1},
{id:5,name:'部门E',parentId:2},
{id:6,name:'部门F',parentId:3},
{id:7,name:'部门G',parentId:2},
{id:8,name:'部门H',parentId:4}
];
// 方式一:
function test(list) {
let res = []
// 按id对Object分类
let maps = list.reduce((pre, cur) => { pre[cur.id] = cur; return pre }, {})
// let maps = new Map(Array.from(list, (x) => [x.id, x]))
console.log('maps', maps)
for(let i = 0, len = list.length; i < len; i++ ) {
let item = list[i]
if(item.parentId === 0) {
res.push(item)
} else {
let parent = maps[item.parentId]
// let parent = maps.get(item.parentId)
parent.children = parent.children || []
parent.children.push(item)
}
}
return res
}
let res = test(list)
console.log(res)
// 方式二:
function buildTree(list, parentId) {
const tree = [];
for (let i = 0; i < list.length; i++) {
if (list[i].parentId === parentId) {
const node = {
id: list[i].id,
name: list[i].name,
children: buildTree(list, list[i].id)
};
tree.push(node);
}
}
return tree;
}
const tree = buildTree(list, 0);
console.log(tree);
// 如果有100个请求,你如何使用Promise控制并发?
const arr = [];
for (let i = 0; i < 100; i++) {
arr.push(
() =>
new Promise((resolve) => {
setTimeout(() => {
console.log("done", i);
resolve();
}, 100 * i);
})
);
}
const parallelRun = () => {
const runingTask = new Map();
const inqueue = (totalTask, max) => {
while (runingTask.size < max && totalTask.length) {
const newTask = totalTask.shift();
const tempName = totalTask.length;
runingTask.set(tempName, newTask);
newTask().finally(() => {
runingTask.delete(tempName);
inqueue(totalTask, max);
});
}
};
return inqueue;
};
parallelRun()(arr, 6);
持续更新中~~