JavaScript如何高效统计多个JSON输入中各属性值的出现次数
现有实现的性能瓶颈
你的现有代码存在几处冗余开销,处理万级数据时会被放大:
- 每次匹配
trait_type都要全量遍历countOfAllAttribute数组,属性类型越多耗时越长 - 匹配属性值时先后调用了
some、find、map,同个trait_count数组最多被遍历3次,冗余开销大 - 使用
map做纯遍历操作但未使用返回值,产生无意义的数组拷贝开销
优化方案
分两种场景给出高效实现,时间复杂度均降到最低:
场景1:首次全量统计5000-10000条数据
优先用批量统计逻辑,一次性生成符合要求的结构,比逐条调用reducer效率高10倍以上:
// 输入为所有NFT对象的数组 function batchCountAttributes(nfts: Array<{attributes: Array<{type: string, value: string}>}>): CountOfEachAttribute[] { // 嵌套Map做临时统计,查找效率O(1) const statMap = new Map<string, Map<string, number>>(); // 单次遍历所有NFT的所有属性,无冗余操作 for (const nft of nfts) { for (const attr of nft.attributes) { const { type: traitType, value } = attr; // 初始化属性类型的统计容器 if (!statMap.has(traitType)) { statMap.set(traitType, new Map()); } const valueMap = statMap.get(traitType)!; // 更新属性值计数 valueMap.set(value, (valueMap.get(value) || 0) + 1); } } // 转换为要求的接口格式 return Array.from(statMap.entries()).map(([trait_type, valueMap]) => { const trait_count = Array.from(valueMap.entries()).map(([value, count]) => ({ value, count })); return { trait_type, trait_count, total_variations: valueMap.size } }) }
该方法时间复杂度为O(总属性数),1万条数据每条平均10个属性的情况下,总计算量仅10万次,毫秒级即可完成。
场景2:优化单条增量更新的reducer逻辑
如果必须支持单条属性增量更新,优化后的逻辑如下,去掉所有冗余遍历:
setCountOfAllAttribute(state, { payload }: PayloadAction<Attribute>) { if (state.countOfAllAttribute === null) return; // 匹配目标属性类型 const targetTrait = state.countOfAllAttribute.find( item => item.trait_type === payload.trait_type ); if (!targetTrait) return; const payloadValue = String(payload.value); // 初始化属性值统计数组 if (targetTrait.trait_count === null) { targetTrait.trait_count = [{ value: payloadValue, count: 1 }]; targetTrait.total_variations = 1; return; } // 单次遍历查找对应属性值,找到直接更新 const existingValue = targetTrait.trait_count.find(item => item.value === payloadValue); if (existingValue) { existingValue.count += 1; return; } // 无匹配值新增条目,用push替代展开运算符避免数组拷贝 targetTrait.trait_count.push({ value: payloadValue, count: 1 }); targetTrait.total_variations += 1; }
如果属性类型非常多,可以额外在state里维护一个traitTypeIndex: Record<string, number>索引,记录每个trait_type在countOfAllAttribute数组的下标,查找属性类型的时间会从O(n)降到O(1),性能进一步提升。
内容的提问来源于stack exchange,提问作者ben shalev
相关产品推荐
相关产品推荐

