【问题标题】:Weirdness when modifying massive json file/array in Node.js在 Node.js 中修改大量 json 文件/数组时的怪异
【发布时间】:2018-07-06 04:56:43
【问题描述】:

我正在处理一个巨大的 json 文件(大约 60 MB),我试图删除其中 volume = 0 的所有条目。数组的格式是

{
  "date": 1424373000,
  "high": 0.33,
  "low": 225,
  "open": 0.33,
  "close": 225,
  "volume": 0.999999,
  "quoteVolume": 0.00444444,
  "weightedAverage": 225
}

为此,我正在使用此代码。

fs.readFile('JSONFiles/poloniexBTCDataFeb19|2015-July2|2018.json', function read(err, data) {
  if (err) {
    throw err;
  }
  rawdata = JSON.parse(data);
  rawdata.forEach(function(val, index, array) {
    if (rawdata[index].volume == 0) {
      rawdata.splice(index, 1)
    }
  })
});

这样做的问题是它只删除了大约一半具有此特征的条目(60k/108k)。我解决这个问题的方法是使用一个运行代码 9 次的 for 循环,这会将它们全部删除,但这会导致代码花费更长的时间,因为整个 json 文件有大约 360k 条目,它必须检查每个条目if 语句。我想知道是否有任何方法可以做到这一点,它实际上可以将它们全部删除,而不必以这种方式使用 for 循环?

编辑:我意识到我首先不需要此代码,所以没关系,但感谢所有答案。我希望这对遇到类似问题的其他人有所帮助。

【问题讨论】:

    标签: javascript arrays json node.js


    【解决方案1】:

    问题是,你正在改变数组rawdata。让我们以一个示例数组 [e1, e2, e3, e4] 和代码为例,

    var arr = ['e1', 'e2', 'e3', 'e4']
    
    arr.forEach(function(elem, idx){
      console.log('checking elem', elem);
      if (elem === 'e2'){
        arr.splice(idx, 1)
      }
    });
    
    console.log('\nAfter iteration', arr);

    如您所见,当我遇到 e2 时,我正在删除它。这会影响实际的数组,并且不会检查被替换的元素(因为 forEach 迭代已经访问了该索引处的元素)。在上面的代码中,e3 没有得到检查。因此,建议不要在 forEach 迭代中改变数组。

    你可以这样做,

    rawdata.slice().forEach(function (val, index, array) {
       if (rawdata[index].volume == 0) {
          rawdata.splice(index, 1)
       }
    });
    

    这里slice() 将创建一个新数组,并且改变你原来的rawdata 不会影响迭代。

    【讨论】:

      【解决方案2】:

      您正在拼接记录,这可能需要一些时间。
      而不是forEach,试试这个:

      var filteredData = rawdata.filter(function (val) {
          return val.volume != 0
      })
      

      【讨论】:

        【解决方案3】:

        您的代码有问题并且错误很常见(在改变数组时迭代数组)。该代码也非常低效,因为要删除的每个元素都会将所有其他元素移动一个位置(您使用splice 的事实并不意味着a 循环没有完成......幕后还有一个循环实现该功能)。

        如果您需要就地从数组中删除元素(即您不想获取副本),一种简单的方法是使用我通常所说的读-跳过-写循环:

        let wp = 0; // the "write pointer"
        for (let x of data) {
            if (keep(x)) data[wp++] = x;
        }
        data.length = wp; // trim unused space
        

        PS:顺便说一句,试着改变你对编程的心态。如果您的第一个想法node 有问题,那么您就不会在编码方面走得太远。现实情况是,您的代码中有 99.99% 的错误发生...寻找其他地方不会让您成为更好的程序员。

        【讨论】:

        • 我知道这通常是我的代码的问题,我并不是说节点中存在错误,我只是不知道如何解释它。我现在更新了标题以更好地解释我的意思。
        猜你喜欢
        • 1970-01-01
        • 2012-11-28
        • 2018-01-28
        • 2018-05-08
        • 1970-01-01
        • 2021-09-04
        • 2019-02-24
        • 2023-01-11
        • 2013-06-25
        相关资源
        最近更新 更多