- 字符串中出现最多的字符以及次数
const input = "aabbccc";
const findMaxStr = (str) => {
const map = [...str].reduce((pre, cur) => {
if (!pre[cur]) {
pre[cur] = 1;
} else {
pre[cur]++;
}
return pre;
}, {});
const [[chart, count]] = Object.entries(map).sort(
([, val1], [, val2]) => val2 - val1
);
return { chart, count };
};
console.log(findMaxStr(input));// {chart: 'c', count: 3}
- 大数相加
const addStrings = (num1, num2) => {
let i = num1.length - 1;
let j = num2.length - 1;
let add = 0;
const answer = [];
while (i >= 0 || j >= 0 || add !== 0) {
const val1 = i >= 0 ? Number(num1[i]) : 0;
const val2 = j >= 0 ? Number(num2[j]) : 0;
const result = val1 + val2 + add;
answer.push(result % 10);
add = Math.floor(result / 10);
i -= 1;
j -= 1;
}
return answer.reverse().join("")
}
const log = console.log;
log(addStrings("123456789", "98765432156464645465")); // 98765432156588100000
- 并发限制 Scheduler
- 类实现
class Scheduler {
constructor(max) {
this.max = max;
this.count = 0; // 执行中的请求数
this.queue = [];
}
async add(promiseCreate) {
if (this.count >= this.max) {
await new Promise((resolve) => this.queue.push(resolve));
}
this.count++;
await promiseCreate();
this.count--;
if (this.queue.length > 0) {
this.queue.shift()();
}
}
}
const delay = (time) =>
new Promise((resolve) =>
setTimeout(() => {
console.log(time);
resolve();
}, time)
);
const scheduler = new Scheduler(2);
scheduler.add(() => delay(1000));
scheduler.add(() => delay(500));
scheduler.add(() => delay(300));
scheduler.add(() => delay(400)); // 500 300 1000 400
- 函数实现
利用协程的概念:
- 4次调用myLimit 或者接受promises 在内部循环4次来调用均可
- 因为是同步调用,所以会执行4次返回的函数, 让前两次的函数继续执行,多余的先阻断(await),并且把释放的方式(resolve),放在一个全局状态(queue)里, 以便其他函数可以访问
- 前两次函数因为没有阻断, 所以会一直走到
await request();, 当走完了,就从queue中取出一个resolve来释放
const createLimit = (max) => {
const queue = [];
let activeCount = 0;
return async (request) => {
if (activeCount >= max) {
// 阻断后面的函数,并且在未来释放时,继续下一行代码开始执行
await new Promise((resolve) => queue.push(resolve));
}
activeCount++;
await request();
activeCount--;// 不减也行, 因为只需要知道阻断2之后即可
if (queue.length) {
queue.shift()();
}
};
};
const myLimit = createLimit(2);
myLimit(() => delay(1000));
myLimit(() => delay(500));
myLimit(() => delay(300));
myLimit(() => delay(400));
- 并发限制: 手动触发
class TaskPool {
constructor(max, callback) {
this.queue = [];
this.max = max;
this.callback = callback;
this.index = 0;
this.allLength = 0;
}
add(fn) {
this.queue.push(fn);
this.allLength = this.queue.length;
}
run() {
while (this.max && this.queue.length > 0) {
this.max--;
const idx = this.index;
this.index++;
this.queue
.shift()()
.then(() => {
this.max++;
if (idx === this.allLength - 1) {
this.callback();
} else {
this.run();
}
// this.run();
});
}
}
}
const delay = (time) =>
new Promise((resolve) =>
setTimeout(() => {
console.log(time);
resolve();
}, time)
);
const taskPool = new TaskPool(2, () => console.log("success"));
taskPool.add(() => delay(1000));
taskPool.add(() => delay(500));
taskPool.add(() => delay(300));
taskPool.add(() => delay(400));
taskPool.run();
// 500 300 1000 400
const obj = {
a: {
b: 1,
c: 2,
d: {
e: 5,
},
},
b: [1, 3, { a: 2, b: 3 }],
c: 3,
};
// 返回值
// {
// 'a.b': 1,
// 'a.c': 2,
// 'a.d.e': 5,
// 'b[0]': 1,
// 'b[1]': 3,
// 'b[2].a': 2,
// 'b[2].b': 3
// 'c': 3
// }
const flatten = (input) => {
const output = {};
const fn = (child, parentPath) => {
if (Array.isArray(child)) {
child.forEach((item, index) => {
const fullPath = parentPath
? `${parentPath}[${index}]`
: `[${index}]`;
fn(item, fullPath);
});
} else if (child && typeof child === "object") {
Object.entries(child).forEach(([k, v]) => {
const fullPath = parentPath ? `${parentPath}.${k}` : k;
fn(v, fullPath);
});
} else {
output[parentPath] = child;
}
};
fn(input, "");
return output;
};
console.log(flatten(obj));