【问题标题】:How to increase the performance如何提高性能
【发布时间】:2018-05-18 16:19:41
【问题描述】:

我有一个名为 records 的对象数组,其中包含 100 多个字段,我需要映射每个对象以创建一个名为 products 的数组以添加一个字符串。我应该如何着手提高性能?

谢谢

for (var i = 0; i < records.length; i++) {
  var products = []
  if (records[i].Custom_BA1__c === 'true'){ products.push('Custom BA1')}
  if (records[i].Custom_Web_Sim__c === 'true'){ products.push('Custom Web Sim')}
  if (records[i].Finance_for_Non_Financials__c === 'true'){ products.push('Finance for Non Financials')}
  if (records[i].Custom_Board__c === 'true'){ products.push('Custom Board')}
  ...
}

【问题讨论】:

  • 调查网络工作者...生成 4 - 8 个子进程并将处理拆分为这 4 - 8 个子进程。
  • 它们是否匹配多个?
  • records 实际有多长?
  • native for loop 最快,可以缓存长度。 refer
  • @Sagar 这无关紧要,您可以从中获得的微优化甚至可能是有害的。

标签: javascript arrays performance object


【解决方案1】:

// Data from somewhere else
var records = [{
    "Custom_BA1__c": "true",
    "Custom_Web_Sim__c": "false",
    "Finance_for_Non_Financials__c": "true"
}];


var mapping = {
    "Custom_BA1__c": "Custom BA1",
    "Custom_Web_Sim__c": "Custom Web Sim",
    "Finance_for_Non_Financials__c": "Finance for Non Financials"
};

for(let record of records){
    let products = Object.entries(record)
                   .filter(([k,v]) => v === "true")  // filter the ones that are "true"
                   .map(([k,v]) => mapping[k]);      // map them to the correct names
    console.log(products);
}

【讨论】:

  • 我看不出这些答案中的任何一个如何比 OP 的代码更高效。我宁愿看到它们更糟,性能方面,这是我如何看待问题的主要方面。
  • @ASDFGerte 这更有效,因为它避免了不必要的函数调用和数组操作。在功能上处理这一点可以大大提高性能。
  • 这将比 for() 循环慢得多。我强烈建议 OP 使用 jsPerf 对自己的代码进行测试以亲自查看。
  • @RandyCasburn 之所以首选.map 而不是反复调用.push 是有原因的。没有任何支持,您的回答同样愚蠢。
  • 在这种情况下,JSPerf 可能会有所帮助(与本网站上成千上万的虚假 JSPerf 性能主题不同),但在您实际使用更大的数据集时。我不想让话题偏离“为什么要极其谨慎地对待 JSPerf”。 OP 还没有回答 records 实际上有多大(也许这只是一个 Knuth,“过早的优化是万恶之源”,你知道的)。
【解决方案2】:

在 ES6 中:

let products = records.map(record => {
  let mapping = {
    'Custom_BA1__c': 'Custom BA1',
    'Custom_Web_Sim__c': 'Custom Web Sim',
    'Finance_for_Non_Financials__c': 'Finance for Non Financials',
    'Custom_Board__c': 'Custom Board'
  }

  return Object.keys(mapping).filter(key => record[key]).map(key => record[key])
}).flatten()

【讨论】:

  • 这将比for() 循环慢得多。我强烈建议 OP 使用 jsPerf 对自己的代码进行测试以亲自查看。
【解决方案3】:

您将要创建一棵二叉树。 对于每条记录,您将遵循通过二叉树的特定路径。 当您到达底部时,树元素将有一个字符串数组,您将通过一次调用将其连接起来。

每个树节点如下所示:

{
 var str;
 var strings;
 var left, right;
}

您将分两步填充树。

第一次通过,在每个级别,您为该级别输入字符串。

                                                         root
                                 left Node {str: 'Custom BA'}                                right Node {str: ''}
left Node {str: 'Custom Web Sim'}  right Node {str: ''}         left Node {str: 'Custom Web Sim'}  right Node {str: ''}

第二次通过,在每个级别,您将放入该级别的聚集数组。

                                                         root
                                 left Node {strs: 'Custom BA'}                                             right Node {strings: []}
left Node {strings: ['Custom BA', 'Custom Web Sim']}  right Node {strings: ['Custom BA']}   left Node {strings: ['Custom Web Sim']}  right Node {strings: []}

现在,一旦数组被填充,给定任何记录,您将遍历树到底部。在每个级别,如果给定字段为“真”,则向左走,否则向右走。 您基本上是在通过时将单个节点变量更新为当前节点。 到达底部后,您调用:

products.concat(node.strings)

你问为什么这么快?因为不是每条记录执行 100 次推送,而是每条记录执行 1 次连接。

遍历树并不比您已经拥有的一系列 if 语句慢,您只是更新单个节点变量,而不是使用每个 'if' 语句进行推送。

对于少量记录,这可能需要更长的时间,因为填充树需要时间。但是随着记录数量的增加,这会更快。

树会变大,是字段数的 2 次方,这对于 100 个字段来说非常大。因此,您可能希望将其分成几棵树,每棵树有 20 个字段(每棵树 2 到 20 个字段大约为几兆字节)。然后您只需按顺序单独遍历每棵树。

另一种优化是跳过填充树的第 2 步,而是在进行时填充。如果您遍历树以获取记录并在最后一个节点处看到“字符串”数组未填充,则重复相同的路径并填充它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-02
    • 2021-06-13
    • 2020-09-09
    • 2012-06-24
    • 2021-05-28
    • 2020-03-31
    • 2020-06-20
    • 1970-01-01
    相关资源
    最近更新 更多