【问题标题】:Compare two big arrays value for value in Node.js在 Node.js 中比较两个大数组的值
【发布时间】:2020-04-03 12:42:17
【问题描述】:

我有两个数组,一个包含来自 CSV 文件的 200.000 个产品对象,另一个包含来自数据库的 200.000 个产品对象。

两个数组都包含具有相同字段的对象,但有一个例外:数据库对象也具有唯一 ID。

我需要将所有 200.000 个 CSV 对象与 200.000 个数据库对象进行比较。如果 CSV 对象已存在于数据库对象数组中,我将其与匹配的 ID 一起放入“更新”数组中,如果不存在,则将其放入“新”数组中。

完成后,我更新数据库中的所有“更新”对象,并插入所有“新”对象。这很快(几秒钟)。

然而,比较步骤需要几个小时。我需要比较三个值:通道(字符串)、日期(日期)和时间(字符串)。如果三个都相同,那就是匹配。如果其中一个不是,那么它就不匹配。

这是我的代码:

  const newProducts = []; 
  const updateProducts = [];
  csvProducts.forEach((csvProduct) => {

    // check if there is a match
    const match = dbProducts.find((dbProduct) => {
      return dbProduct.channel === csvProduct.channel && moment(dbProduct.date).isSame(moment(csvProduct.date), 'day') && dbProduct.start_time === csvProduct.start_time;
    });

    if (match) {
      // we found a match, add it to updateProducts array
      updateProducts.push({
        id: match.id,
        ...csvProduct
      });

      // remove the match from the dbProducts array to speed things up
      _.pull(dbProducts, match);
    } else {
      // no match, it's a new product
      newProducts.push(csvProduct);
    }
  });

我正在使用 lodashmoment.js 库。

瓶颈在于检查是否有匹配,关于如何加快速度的任何想法?

【问题讨论】:

    标签: arrays node.js performance compare


    【解决方案1】:

    这是Map collection class 的工作。数组很麻烦,因为它们必须线性搜索。可以快速搜索地图(和Sets)。您希望在 RAM 中进行匹配,而不是为传入文件中的每个对象访问数据库。

    因此,首先读取数据库中的每条记录并构造一个 Map,其中键是 {start_time, date, channel} 之类的对象,值是 id。 (我把时间放在第一位,因为我猜它是具有最多不同值的属性。这是为了加快查找速度。)

    类似这样的伪代码。

     const productsInDb = new Map()
     for (const entry in database) {
         const key = {  // make your keys EXACTLY the same when you load your Map ..
             start_time: entry.start_time,
             date: moment(entry.date), 
             entry.channel}
         productsInDb.add(key, entry.id)
     }
    

    这会占用大量内存,但那又如何呢?这就是 RAM 的用途。

    然后或多或少地按照您在示例中的方式进行匹配,但使用您的地图。

    const newProducts = []; 
    const updateProducts = [];
    csvProducts.forEach((csvProduct) => {
    
      // check if there is a match
      const key = {     // ...and when you look up entries in the Map.
             start_time: entry.start_time,
             date: moment(entry.date), 
             entry.channel}
      const id = productsInDb.get(key)
      if (id) {
          // we found a match, add it to updateProducts array
          updateProducts.push({
             id: match.id,
            ...csvProduct
          });
          // don't bother to update your Map here 
          // unless you need to do something about dups in your csv file
      } else {
        // no match, it's a new product
        newProducts.push(csvProduct)
      }
    });
    

    【讨论】:

    • 谢谢,成功了!现在只需几秒钟 :)
    • 酷。几小时到几秒。 O(n**2) 到 O(n log n) 总是有所作为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2017-11-01
    • 1970-01-01
    • 2015-06-30
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多