如何在不修改原数组时找高频元素?如何将给定JS代码重构为不可变实现?
嘿,这两个问题我都熟,来给你拆解清楚:
问题1:不修改原数组找出出现次数最多的元素
要做到完全不修改原数组,核心就是只读取原数组的内容,所有中间操作都用新的对象/数组来承载,绝不改动原数组的任何元素或结构。这里最简洁的方式是用reduce统计每个元素的出现频率,再从中找出次数最高的那个:
const arr1 = [3, 'oo', 'oo', 'oo', 2, 3, 'oo', 3, 'oo', 2, 4, 9, 3]; // 第一步:用reduce统计频率,每次返回新对象,不修改原数组 const frequencyMap = arr1.reduce((acc, current) => { return {...acc, [current]: (acc[current] || 0) + 1}; }, {}); // 第二步:遍历频率对象,找出次数最多的元素 let maxCount = 0; let mostFrequentItem; for (const [item, count] of Object.entries(frequencyMap)) { if (count > maxCount) { maxCount = count; // 处理类型转换:如果原元素是数字,把字符串键转回数字 mostFrequentItem = isNaN(Number(item)) ? item : Number(item); } } console.log(`${mostFrequentItem} ( ${maxCount} times )`);
这段代码全程没碰原数组arr1,reduce里用扩展运算符...acc创建新对象,避免修改原累加器,完全符合“不修改任何内容”的要求。
问题2:重构为纯JS的不可变实现
原代码的嵌套循环写法不仅冗余,而且用了可变变量(mf、m、item都是可重新赋值的var变量)。我们可以把它改成无副作用的纯函数,全程不修改任何外部状态,所有操作都基于新创建的结构:
const arr1 = [3, 'oo', 'oo', 'oo', 2, 3, 'oo', 3, 'oo', 2, 4, 9, 3]; // 纯函数:只依赖传入的数组,返回结果,不修改任何外部内容 const findMostFrequentItem = (arr) => { // 1. 不可变统计频率 const frequencyMap = arr.reduce((acc, current) => { return {...acc, [current]: (acc[current] || 0) + 1}; }, {}); // 2. 转换为条目数组,方便后续处理 const frequencyEntries = Object.entries(frequencyMap); // 3. 用reduce找出次数最高的条目,全程不修改外部变量 const [topItemStr, topCount] = frequencyEntries.reduce((maxEntry, currentEntry) => { return currentEntry[1] > maxEntry[1] ? currentEntry : maxEntry; }, ['', 0]); // 修正类型:把字符串键转回原类型(数字/字符串) const topItem = isNaN(Number(topItemStr)) ? topItemStr : Number(topItemStr); return `${topItem} ( ${topCount} times )`; }; // 调用函数,原数组完全不受影响 console.log(findMostFrequentItem(arr1));
为什么这是不可变实现?
- 所有中间状态(
frequencyMap、frequencyEntries)都是新创建的,没有修改任何外部变量 reduce里每次返回新对象,绝不修改原累加器- 函数不依赖外部状态,传入相同的数组会得到相同的结果,没有任何副作用
内容的提问来源于stack exchange,提问作者zawhtut
相关产品推荐
相关产品推荐

