背景

在解决http://jira.iguming.net:8080/browse/XSWT-1422问题的时候,因为基本上所有读的接口都存在延迟的情况,所以判断有无更新不应该只是判断长度的更新。如果是配置角色,此时更新前后的数组长度不变,此时需要准确的检测更新机制。

思路

首次尝试:遍历+JSON.stringify

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 判断两个数组是否一样
export const compareArraySame = (arr1, arr2) => {
if (!arr1) arr1 = [];
if (!arr2) arr2 = [];
return (
arr1.length === arr2.length &&
arr1.every((item1) =>
arr2.map((item2) => JSON.stringify(item2)).includes(JSON.stringify(item1))
) &&
arr2.every((item2) =>
arr1.map((item1) => JSON.stringify(item1)).includes(JSON.stringify(item2))
)
);
};

缺点:

  • 性能低:时间复杂度$O(N^3)$(every, map, includes, &&)
  • 不一定准确:JSON.stringify如何处理的对象顺序不一致,就不准确

提取相同key,排序后join比对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 判断两个数组是否一样
const compareArraySame = (arr1, arr2) => {
if (!arr1) arr1 = [];
if (!arr2) arr2 = [];
// 变化的只有name和role
const comp1 = arr1.map(item=>[item.id+item.name+item.role]);
const comp2 = arr2.map(item=>[item.id+item.name+item.role]);

// 顺序可能变化
comp1.sort()
comp2.sort()

return (
arr1.length === arr2.length &&
comp1.join('-') === comp2.join('-')
);
};

分析

对于本次需求来讲,会变化的除了长度外,具体字设计到的字段只有2个:name和role。所以可以把对象数组的这两个字段拼出来,然后排序合并比对。此方法有两个注意点:

  1. 排序:因为修改角色后,数字可能会重新按照首字母排序
  2. 拼接的时候,得加上id表标识

时间复杂度

map —> O(N), sort —> O(NlognN, join —> O(N)

所以时间复杂度为O(2N+2NlogN+2*N)=O(NlogN)

缺点

方法不具有通用性

总结

第二种方法性能更好一点。值得注意的是,如果对性能要求很高,命令式变成比声明式编程会好一点.

参考资料

How To Calculate Time Complexity With Big O Notation

Big O Cheat Sheet – Time Complexity Chart

Performance of JavaScript .forEach, .map and .reduce vs for and for..of

模板—【🌀🌀🌀TODO】 (1)