如何在 javascript 中最有效地对规范化数据进行非规范化

Posted

技术标签:

【中文标题】如何在 javascript 中最有效地对规范化数据进行非规范化【英文标题】:How to denormalize normalized data most effectively in javascript 【发布时间】:2021-09-05 06:36:30 【问题描述】:

例如我有以下树:

root: 
  a: 
    b: null,
    c: 
      d: null
    
  
  e: null

我以 [child]: parent 的形式收到它:


  a: 'root',
  e: 'root',
  b: 'a',
  c: 'a',
  d: 'c'

但我没有收到上述订购的产品。不过,我愿意。

如果我知道根项(没有父项)是root,我可以使用这个函数:

const recurs = (obj, cb, parent = 'root') => Object.entries(obj)
  .filter(([child, childsParent]) => childsParent === parent)
  .forEach(([child]) => 
    cb(child);
    recurs(obj, cb, child);
  );

但是因为它是递归的,所以它可以填满内存,因为在一切完成之前不会对父母进行垃圾收集。有没有更有效的方法来做这种事情?这可以转换为for循环吗?

【问题讨论】:

"可以将其转换为 for 循环吗?" 可以。但是,为什么您认为这将有助于垃圾收集?通常 GC 会等到循环完成后才会运行。您是否真正观察到问题或者这是过早的优化? 它可以填满内存,因为父母不会被垃圾收集”是什么意思? 无法保证 GC 何时运行。它通常会等待程序不忙。它可能在循环期间运行,但通常会导致性能大大降低(如果它运行一次,它可能会运行更多次。一个大循环会产生很多符合 GC 条件的东西,那就是会有很多 GC 停止)。 这让我们回到“你是否真的注意到这是一个问题”,因为现在听起来你正在尝试优化一些没有实际性能或可用性的东西(dev or 用户)问题,因此不需要花费任何时间。 我认为也许 OP 关心的是调用堆栈而不是 GC,因为问题是关于避免递归? 【参考方案1】:

使用在单个线性循环中填充的查找表:

const edges = 
  a: 'root',
  e: 'root',
  b: 'a',
  c: 'a',
  d: 'c'
;

const forest = ;
for (const child in edges) 
  const parent = edges[child];
  forest[parent] ??= ;
  forest[child] ??= ;
  forest[parent][child] = forest[child];

const tree = forest.root;

【讨论】:

@pilchard 谢谢,已修复

以上是关于如何在 javascript 中最有效地对规范化数据进行非规范化的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP 和 MySQL 有效地对大型数据集进行分页?

如何有效地对抽象列表进行嵌套迭代?

在有效的 PHP query() XPath 中转换 Javascript XPath |规范化 JS XPath --> PHP

在 Java 中有效地对图像进行颜色循环

如何高效地对大量数据进行分区? [关闭]

javascript:void 含义代码规范