返回
用 shuffle 探究编码者的品味(面试问题)
前端
2024-01-23 09:23:19
软件开发中的代码审查常常是一项艰巨的任务,尤其当你在与新的开发团队合作时。这时候,你很有可能看到一些让你疑惑的代码实现,例如,随机函数 shuffle 的使用。shuffle,顾名思义,就是将数组随机排序,常被开发人员用作实现随机功能。
我们来看一下 shuffle 可以如何体现出代码品味。
首先,思考一下这个问题:为什么要把 i 和 randomIndex 的声明放在最前端?
ES5 中的变量提升(ES6 中有无变量提升…)。
其次,我们看看这两个函数是怎样处理参数的:
function shuffle_1(array) {
const n = array.length;
for (let i = 0; i < n; i++) {
const randomIndex = Math.floor(Math.random() * (n - i)) + i;
const temp = array[i];
array[i] = array[randomIndex];
array[randomIndex] = temp;
}
}
function shuffle_2(array) {
const n = array.length;
for (let i = 0; i < n; i++) {
const randomIndex = Math.floor(Math.random() * n);
const temp = array[i];
array[i] = array[randomIndex];
array[randomIndex] = temp;
}
}
shuffle_1() 在每个循环中都计算 n - i,而 shuffle_2() 则只计算一次 n。这使得 shuffle_2() 在数组较大时具有更好的性能,因为 n - i 会随着循环次数的增加而变小。
最后,这两个函数是如何处理边界情况的:
function shuffle_3(array) {
const n = array.length;
for (let i = 0; i < n; i++) {
const randomIndex = Math.floor(Math.random() * n);
if (randomIndex === i) {
continue;
}
const temp = array[i];
array[i] = array[randomIndex];
array[randomIndex] = temp;
}
}
function shuffle_4(array) {
const n = array.length;
for (let i = 0; i < n; i++) {
const randomIndex = Math.floor(Math.random() * n);
if (randomIndex === i) {
randomIndex = (randomIndex + 1) % n;
}
const temp = array[i];
array[i] = array[randomIndex];
array[randomIndex] = temp;
}
}
shuffle_3() 在遇到 randomIndex 等于 i 的情况时,会跳过本次循环,继续进行下一次循环。shuffle_4() 则会在遇到 randomIndex 等于 i 的情况时,将 randomIndex 加 1 并取模 n,确保 randomIndex 不等于 i。
通过以上三个方面的比较,我们可以看到 shuffle_2() 和 shuffle_4() 在性能和边界情况处理方面都优于 shuffle_1() 和 shuffle_3()。因此,在实际开发中,我们应该选择 shuffle_2() 和 shuffle_4()。