javascript - 在 Javascript 中比较两个对象数组与文字值的更快方法
问题描述
- 具有字面值的对象数组意味着,它是一个数组,它的每个元素都是一个对象,而这样的对象的值都是字面量(所以它不会是嵌套对象,对象内的数组等),例如,它可:
[ { name: 'Bob', age: 20, isMale: true }, { name: 'Alice', age: 19, isMale: false}, ... ]
- 比较的意思是,我们需要区分
added
和removed
元素,例如:
const original = [ { name: 'Bob', age: 20, isMale: true }, { name: 'Alice', age: 19, isMale: false} ];
const modified = [ { name: 'Alice', age: 19, isMale: false}, { name: 'Jay', age: 21, isMale: true } ];
// then added = [{ name: 'Jay', age: 21, isMale: true }]
// and removed = [{ name: 'Bob', age: 20, isMale: true }]
我的方法:使用 lodash 的differenceWith和isEqual使事情正常进行,例如:
const original = [ { name: 'Bob', age: 20, isMale: true }, { name: 'Alice', age: 19, isMale: false} ];
const modified = [ { name: 'Alice', age: 19, isMale: false}, { name: 'Jay', age: 21, isMale: true } ];
const removed = _.differenceWith(original, modified, _.isEqual);
const added = _.differenceWith(modified, original, _.isEqual);
^ 然而,这还不够快!我有两个数组的样本,每个数组包含 10K+ 个对象,而每个对象有 3 个属性值。像这样:
[{lat: 123.321, long: 234.432, radius: 100}, ....] // 10K+ elements
我自己测试过,使用我的方法将花费:
- ~10 秒完成 <= 太慢了
- 由于计算量大,浏览器将冻结 <= 主要问题!
现在,问题是,您能否提供一种更快、更优雅的方法来比较此类样本?
我的一个猜测是我可以通过将其替换isEqual
为其他东西来改进,但不确定它在这种情况下是否有帮助。
解决方案
将每个对象与每个对象进行比较会导致O(n^2)
问题,正如您所注意到的那样,复杂性增长得非常快,然后 10k 个对象(这在计算机世界中并不多)几乎无法处理。
然而,有更简单的方法来解决这个问题。
预处理
- 按名称对两个数组进行排序,这需要
O(n*log(n))
- 每个数组都有两个索引,从 开始
0
,让我们调用它i
并j
处理
- 比较名称
original[i]
和modified[j]
- 如果它是相同的,只是
i++
和j++
- 如果不同,则检查字符串比较中哪个“更低”(就像 Bob 低于 Cathrine,因为它以 开头
B
) - 如果
original[i]
低于,将其添加到removed
和i++
- 如果
modified[j]
低于,将其添加到added
和j++
- 重复直到处理两个数组
最昂贵的部分是排序,其他一切都O(n)
及时完成,因此整体复杂性O(n*log(n))
即使对于数百万个项目也足够好。
注意:如果您还需要比较即年龄或性别,而不仅仅是姓名,您需要更新以上内容,按多个字段排序,然后按多个字段进行比较)
推荐阅读
- mysql - 使用 GROUP BY 获取适当的日期
- javascript - 在反应原生 WebView 中添加自定义 html 标签
- reactjs - 限制对 AWS Amplify GraphQL 中的列表的访问
- docker - Next Js 部署水平扩展使用 docker 在启用多个 Pod 时失败
- mysql - 如何为所需的输出创建视图
- android - MVVM Android 应用中的 JUnit 测试 ViewModel
- python - 包括使用 cx_freeze 编译的扩展
- c++ - “ferror”测试“scanf”输入
- spring-boot - java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String,[B,int,int,java.lang.ClassLoader,java.security.ProtectionDomain)
- r - 如何将绘图标签放在ggplot方面