【问题标题】:Big O Notation and functional programming in javascriptjavascript 中的大 O 表示法和函数式编程
【发布时间】:2023-06-07 15:46:01
【问题描述】:

我正在尝试使用reduce() 理解和陈述以下算法的大 O 表示法。我的理解是reduce是一个应用于数组对象的函数。它接受一个回调和一个初始值。下面的代码是一个保存算法的控制器:

export const getPublicID = (req, res) => {
  const data = req.body.result;
  if (!data) res.status(422).json({ success: false, message: 'Upload Failed!' });
  console.time('ARRAY');
  const insertStuff = data.reduce((array, item) => {
    array.push({
      public_id: item.public_id,
      url: item.url,
      thumbnail_url: item.thumbnail_url
    });

    return array;
  }, []);
  console.timeEnd('ARRAY');

  Photo.insertMany(insertStuff)
    .then(
      img => res.status(201).json({
      success: true,
      message: 'Successfully added to database.',
      cloudinary: img
     }),
     err => res.status(422).json({ success: false, message: err })
    );
};

req.body.result 以对象数组的形式出现,通过 reduce 方法,我创建了自己的对象数组,然后将其插入到我的 MongoDB 集合中。 Reduce 正在遍历数组,所以我认为这是 O(n),因为存在的元素越多,迭代所需的时间就越多,因此是一个线性图。如果这是正确的假设,我的三个问题是以下如何影响我的算法:

  1. push()
  2. insertMany()
  3. 承诺

感谢您帮助数据结构和算法的菜鸟了解代码的优缺点,非常感谢!

【问题讨论】:

  • insertMany 似乎是一个异步调用。运行时间可能会有所不同。
  • @RajaprabhuAravindasamy 我将不得不对此进行研究,但我相信你是对的,这是 Mongo 图书馆的一种方法。

标签: javascript arrays mongodb algorithm


【解决方案1】:

Big O 描述了渐近性能,更具体地说,它给出了算法时间复杂度的上限。这意味着它不看函数需要多少实际时间,可能是 1 毫秒,也可能是 1 分钟,只看算法的效率。

O(n) 表示脚本将在线性时间内运行。 例如:

for(int i=0; i<n; ++i) {
   print(i);
}

现在,如果您需要再次通过该阵列运行,您将获得不同的性能。

O(n^2) = O n 平方 = 外环 (i) x 外环 (x)

for(int i=0; i<n; ++i) {
    for(int x=0; x<n; ++x) {
        print(x);
    }
}

现在看看你在做什么,你的分析走在了正确的轨道上,你在循环中没有循环,只是顺序循环。

push(),虽然它是由 reduce() 而不是 push() 决定的。 insertMany() 将承诺作为它的一部分。这不是一个额外的循环,只是一个正在执行的函数。

这意味着您有两个循环。有些人会说这给了你 O(2n),但其他人声称没有这样的事情,也不会有所作为。

底线: 看看 Big O 的目的,它关注的增长率仍然是线性的,它仍然给你 O(n)。

【讨论】:

  • 所以在大多数情况下,假设性地说,如果您想查看算法的大 O 表示法,您可以忽略 Promise,这是有道理的,因为 Promise 只是在等待我们所设置的任何变量宣布应许。我不确定push(),所以它被认为是一个循环?
  • @cody,这是关于逻辑效率的。因此,如果您有一组 10 个项目,并且为每个项目(循环)运行 1 个或 3 个函数,那么在渐近性能的眼中这并不重要。它仍然是线性的,因为它不会根据输入而改变。另一方面,如果您有 10 个项目,并且每个项目都包含另外 10 个您需要处理的项目,那么您在循环中就有一个循环。 'push()' 不是循环,而是循环'reduce()' 运行的函数。此方法在每个元素上运行一个函数,因此您可以将其视为一个循环。希望这会有所帮助。
  • @Robert -- 那么我们可以说做类似....myArray.reduce().reduce() 也相当于 O(2n) 或 O(n) 吗?