天天看点

9 个用于算法的简洁 JavaScript 代码段

9 个用于算法的简洁 JavaScript 代码段

英文 | https://medium.com/geekculture/9-neat-javascript-one-liners-for-algorithms-and-more-8dd3b0a0fb6d

翻译 | 杨小爱

了解一些JavaScript 单行代码片段可以在开发或面试时为你节省宝贵的时间。以下是我在编码时,实际开发中,我最喜欢的一些JavaScript的代码片段。

希望对你有所帮助。现在,我们就开始吧。

01、循环一个列表

循环是一个巧妙的技巧,很多时候在算法中你需要循环一个列表。意思是移动多个空格,如果到达列表末尾,则返回到第一个索引。

因此,如果列表的长度为 8 个值,但你必须移动 10 个值,则你需要落在第二个索引上。

​你可以使用一堆复杂的 if 语句,或者……

const wrap = (arr, steps) => arr[steps % arr.length];
wrap(['a','b','c'], 0) // a 
wrap(['a','b','c'], 1) // b
wrap(['a','b','c'], 2) // c
wrap(['a','b','c'], 3) // a 
// etc ...      

您可以根据步骤以不同的方式实现这一点,但要理解的关键是modulo。这是一个方便的小运算符。在查看此类“溢出”类型问题时请记住它。

02、用它的名字记录一个变量

这是调试时的一个很好的技巧。多亏了对象速记符号,我们可以默认用名称注销变量。

const someVar = 1;
console.log({ someVar });
// logs out { someVar: 1 }      

如果您放入一堆日志(并且在调试时您完全会这样做),则可能很难跟踪哪个是哪个,所有异步、获取和循环都在四处奔波。不必花时间输入像 console.log('some var', someVar) 这样的多个参数,而是在一些大括号中折腾并称它为一天。

03、对象中的可选属性

如果您不希望属性指向 undefined 或 null ,您可以使用一些 if 语句来选择性地添加属性:

//...
const obj = {
  a: 'whatever',
};
if (b) {
  obj.c = 'ok';
}
return obj;
//...      

然而,它太冗长了,我一直讨厌它。这可能很清楚,但很笨拙。好吧,由于对象传播,这已成为过去:

return {
  a: 'Whatever',
  ...(b && { c: 'ok'}),
};      

我们可以使用扩展和&&逻辑短路来动态检查是否通过扩展来添加属性。当您只想返回一个对象而不想创建临时变量时,这非常有用。

04、在 JavaScript 中睡眠

有几次我不得不处理一个很糟糕的 API,它很慢,而且在它完成时没有钩子可以说。因此,我们只需要等待一秒钟以确保它已加载。我们还想使用 promises 而不是 setTimeout 回调,因此使用 sleep 函数是理想的。我们可以简单地等待一秒钟,然后继续前进。不需要回调!

const sleep = (ms) => new Promise(r => setTimeout(r, ms));      

这也是如何承诺 setInterval 。

05、交换变量值

在现代 JS 之前,如果你想切换两个变量的值,你必须引入第三个“临时”值。现在我们有了数组解构和赋值,我们可以在一行中完成:

a = 10;
b = 5;
[a,b] = [b,a];
// a is 5, b is 10      

06、四舍五入到最接近的 10、100、1000……

如果您需要将数字粗略计算到不同级别,这在算法中很有用。基本上,您要做的是先除以将小数向上移动。“无用”数字现在是小数,您可以将它们四舍五入。要将数字恢复到所需大小,请将其相乘。被忽略的数字现在变成零。这是处理金钱或类似对数的尺度的巧妙技巧,在某个点之后,小数字可以四舍五入。

const rounder = (val, place) => Math.round(val / place) * place;
rounder(1549, 100); // 1500
rounder(15590, 1000); // 16000      

07、使用 Set 删除重复项

我刚刚写了关于 Sets 的文章,显然这是它们唯一的用途。如果您有一个数组并且想要删除重复项,则可以使用 Set 来完成。

const val = [...new Set([1,2,1,3,1,4])];
// [ 1, 2, 3, 4 ]      

不要忘记将新 Set 散布回常规数组中。注意:处理大量列表时要小心,因为这可能不是性能最高的解决方案。

08、计数字符实例

如果您有一个数组(或来自字符串的数组)并且想知道字符出现了多少次,那么使用 reduce 有一种非常巧妙的方法可以做到这一点。

const charTotals = (arr) => arr.reduce((totals, char) => ({ 
  ...totals, [char]: (totals[char] || 0) + 1, 
}), {});
charTotals('Hi there!'.split(''));
// { H: 1, i: 1, ' ': 1, t: 1, h: 1, e: 2, r: 1, '!': 1 }      

这个可能不是那么有用,但是我想确保您知道两种技术:动态对象属性和对象的隐式返回。这两件事都是至关重要的知识,如果您不了解 reduce,请阅读本文。

09、身份证制造商/柜台

我想我需要为反应组件动态创建非数据库临时 ID,并将经典计数器压缩到一行中。每次调用该函数时,计数器都会增加,并且没有其他函数可以改变其内部状态。它使用闭包、立即调用函数表达式和默认值来保持紧凑。

const counter = ((num = 1) => () => num++)();
counter() // 1
counter() // 2
counter() // 3      

还有一个额外提示,即在函数参数中使用默认值以避免需要换行。如果你真的想让起始数字变得动态,你可以停止让它成为 IIFE:

const startCounter = (num = 1) => () => num++);
const counter100 = startCounter(100)
counter100() // 100
counter100() // 101
counter100() // 102      

总结

你得到了代码的简洁,也有可能你失去代码的可读性。

最终如何取舍,这取决于您和您的团队喜欢什么,在编程的世界里,没有完美,只有谁更加符合需求,符合项目进度。因此,请不要刻意追求简洁,保持代码的可读性依然重要。

最后,感谢您的阅读,祝您编码愉快。

继续阅读