处理用户关联费用场景的最佳数据结构是什么?
优化用户-费用关联数据结构的方案
你当前用两个哈希表的思路没问题,核心问题出在删除费用时的遍历逻辑——其实完全不需要遍历整个userList,利用现有数据里的关联关系就能做到高效删除,树结构反而没必要,哈希表本身就可以满足高效操作的需求。
核心优化思路
每个费用对象里已经存了userId,这就是关键的关联线索!删除费用时,直接通过这个userId定位到对应的用户,不用遍历所有用户:
具体删除步骤(基于原数据结构)
function deleteExpense(expId) { // 1. 拿到要删除的费用对象,O(1)查找 const expense = expenseList[expId]; if (!expense) return; const userId = expense.userId; // 2. 通过userId定位到对应用户,O(1)查找 const user = userList[userId]; if (!user) return; // 3. 从用户的expenseIds数组中移除该费用ID user.expenseIds = user.expenseIds.filter(id => id !== expId); // 或者用splice(需先找到索引) // const index = user.expenseIds.indexOf(expId); // if (index !== -1) user.expenseIds.splice(index, 1); // 4. 从expenseList中删除该费用,O(1)操作 delete expenseList[expId]; }
进一步提升删除效率:用Set替代数组存储expenseIds
如果用户的费用数量较多,数组的filter或splice是O(n)操作(n为该用户的费用数),换成Set的话,删除操作是O(1),效率更高:
修改后的用户数据结构:
export const userList = { 1: { userId:1, firstname:'Jonathan', lastname: 'Lee', expenseIds: new Set([10, 20, 30, 40]) }, 2: { userId:2, firstname:'Todd', lastname: 'Don', expenseIds: new Set([50]) } };
对应的删除逻辑更简洁:
function deleteExpense(expId) { const expense = expenseList[expId]; if (!expense) return; const user = userList[expense.userId]; if (!user) return; // Set的delete是O(1)操作 user.expenseIds.delete(expId); delete expenseList[expId]; }
额外优化:消除冗余数据
你当前的费用对象里存了fullname,这属于冗余数据——如果用户修改姓名,所有关联的费用都要同步修改。可以改成每次需要显示全名时,通过userId从userList中取firstname和lastname拼接,减少维护成本。
为什么不用树结构?
树结构(比如红黑树)的查找、插入、删除是O(logn),而哈希表的这些操作是O(1)(平均情况),对于你当前的需求(主要是单条数据的增删查),哈希表的效率更高,完全没必要引入树结构。
内容的提问来源于stack exchange,提问作者Jonathan Lee
相关产品推荐
相关产品推荐

