数组去重函数实现疑问:如何处理isSorted与iterator参数?
完善你的数组去重函数
我来帮你把这个基础去重函数升级成支持有序优化和迭代器的版本,刚好对这类数组处理逻辑很熟~
首先得解决参数歧义的问题——用户可能只传迭代器(iterator)而不传isSorted,所以第一步要先把参数逻辑理清楚:如果第二个参数是函数,那它其实是iterator,isSorted默认设为false;如果第二个是布尔值,才是isSorted,第三个是iterator。
接下来结合有序数组的高效特性和迭代器的需求,咱们写出更灵活的实现:
_.uniq = function(array, isSorted, iterator) { var unique = []; // 用来存储迭代器处理后的值,方便快速判断重复 var processedValues = []; // 第一步:处理参数,兼容不同传参方式 if (typeof isSorted === 'function') { iterator = isSorted; isSorted = false; } for (var i = 0; i < array.length; i++) { var ele = array[i]; // 如果有迭代器,先获取元素处理后的值 var processedEle = iterator ? iterator(ele) : ele; if (isSorted) { // 有序数组优化:重复元素必定相邻,只需和结果数组最后一个元素对比 var lastProcessed = unique.length > 0 ? (iterator ? iterator(unique[unique.length - 1]) : unique[unique.length - 1]) : undefined; if (processedEle !== lastProcessed) { unique.push(ele); } } else { // 无序数组:检查处理后的值是否已存在 if (processedValues.indexOf(processedEle) === -1) { unique.push(ele); processedValues.push(processedEle); } } } return unique; };
关键逻辑拆解:
- 参数兼容:支持两种传参方式,比如
_.uniq([1,1,2,3], true)(有序去重)和_.uniq([1,2,1,3], item => item * 2)(按迭代后的值去重)都能正常工作。 - 有序数组优化:利用有序数组重复元素相邻的特性,避免了每次调用
indexOf的O(n)开销,整体时间复杂度降到O(n),大数据量下性能提升明显。 - 迭代器支持:先对元素应用迭代器,用处理后的值判断重复,但保留原数组元素,符合常见的业务需求。
进阶优化(可选):
如果你的运行环境支持ES6,可以把processedValues换成Set,把查找重复的时间复杂度从O(n)降到O(1),处理大数据量时更高效:
// 替换processedValues为Set var processedValues = new Set(); // 无序数组的判断逻辑改成: if (!processedValues.has(processedEle)) { unique.push(ele); processedValues.add(processedEle); }
测试用例参考:
// 有序数组去重 console.log(_.uniq([1,1,2,2,3,4], true)); // 输出 [1,2,3,4] // 带迭代器的无序数组去重 console.log(_.uniq([1,2,4,3,2], item => item % 2)); // 输出 [1,2](按奇偶性去重)
内容的提问来源于stack exchange,提问作者NewProgrammer
相关产品推荐
相关产品推荐

