leetcode 165.版本号比对
发布于 # leetcode
版本号比对
这里讨论的是一些“不正经”的解法,
优雅的函数式风格
const compareVersions = (version1, version2) => {
const parseVersion = (version) => version.split('.').map(Number);
const [v1Parts, v2Parts] = [version1, version2].map(parseVersion);
const maxLength = Math.max(v1Parts.length, v2Parts.length);
const result = Array.from({ length: maxLength })
.map((_, i) => (v1Parts[i] || 0) - (v2Parts[i] || 0))
.find(diff => diff !== 0);
return Math.sign(result || 0);
};
我们首先定义了一个函数parseVersion来解析版本号字符串并将其转换为数字数组。然后,我们使用map方法来创建两个版本号的数组。接下来,我们创建一个长度等于两个版本号中最长的那个的数组,并使用map方法计算每个位置上的版本号差异。最后,我们使用find方法来找到第一个非零的差异值。如果找到了差异值,我们使用Math.sign来确定其符号并返回;如果没有差异值(即所有差异值都为零),那么我们返回0。
迭代器
const compareVersions = (version1, version2) => {
const normalizeVersion = (version, maxLength) =>
version.split('.')
.map(Number)
.concat(Array(maxLength).fill(0));
const maxLength = Math.max(version1.split('.').length, version2.split('.').length);
const [v1, v2] = [version1, version2].map(v => normalizeVersion(v, maxLength));
let comparisonResult = 0;
v1.some((num, idx) => {
if (num !== v2[idx]) {
comparisonResult = Math.sign(num - v2[idx]);
return true; // Stop the iteration as we found a difference
}
return false; // Continue iteration
});
return comparisonResult;
};
使用 some 方法来迭代版本号的每个部分。一旦发现两个版本号在某个位置不相等,我们就通过 Math.sign 函数计算比较结果并立即停止迭代。这意味着如果我们在比较的过程中找到了结果,我们就不会继续进行无用的比较。这种方式是高效的,特别是对于长版本号字符串和早期就可以确定结果的情况。
整活 函数式风格Point-free(又称为 tacit 编程)
const parseVersion = version => version.split('.').map(Number);
const fillZeros = length => Array.from({ length }, () => 0);
const zipWithDefault = (defaultVal, arr1, arr2) =>
arr1.map((val, idx) => [val, arr2[idx] || defaultVal]);
const diffOrZero = ([num1, num2]) => num1 - num2;
const compareArrays = (arr1, arr2) => {
const maxLength = Math.max(arr1.length, arr2.length);
const combined = zipWithDefault(0, [...arr1, ...fillZeros(maxLength - arr1.length)], arr2);
const result = combined.map(diffOrZero).find(diff => diff !== 0);
return Math.sign(result || 0);
};
const compareVersions = (version1, version2) =>
compareArrays(parseVersion(version1), parseVersion(version2));
我们定义了几个辅助函数 parseVersion、fillZeros、zipWithDefault 和 diffOrZero。这些函数都是高阶函数,它们不涉及具体的参数值,而是返回操作这些参数的函数。然后我们使用这些函数来构建 compareVersions 函数,这种方式更符合 point-free 风格。
注意,虽然 point-free 风格看起来很有趣且可以使代码更加简洁,但它并不总是最佳选择。过度使用 point-free 风格可能会使代码难以理解,特别是对于不熟悉这种风格的开发者来说。因此,在实际编程中,应该根据情况权衡代码的可读性和简洁性。