首页 > 解决方案 > 将较大的字节数组转换为字符串

问题描述

什么时候N设置为125K以下作品

let N = 125000
let x = [...Array(N)].map(( xx,i) => i)
let y = String.fromCodePoint(...x)
console.log(y.length)

当 N 设置为128K相同的代码中断时:

未捕获的 RangeError:超出最大调用堆栈大小

这是一个常见的操作:实现转换的最佳方式是什么?

请注意,我确实看过这个相关的 Q&A 。https://stackoverflow.com/a/3195961/1056563 我们不应该依赖node.js并且使用的方法fromCharCode.apply也失败了。最后,这个答案已经有将近十年的历史了。

那么处理这种转换的最新高性能方法是什么?

标签: javascript

解决方案


这个问题是因为实现接受的参数数量限制。当通过扩展运算符向函数提供太多参数(在本例中超过 ~128k)时,这会导致引发异常。String.fromCodePoint

相对有效地解决此问题的一种方法(尽管代码稍多)是跨多个调用批处理操作。这是我提出的实现,它解决了我认为与扩展性能有关的问题以及代理对的处理(这是不正确的:fromCodePoint不关心代理,fromCharCode在这种情况下更可取)。

let N = 500 * 1000;
let A = [...Array(N)].map((x,i) => i); // start with "an array".

function codePointsToString(cps) {
  let rs = [];
  let batch = 32767; // Supported 'all' browsers
  for (let i = 0; i < cps.length; ){
    let e = i + batch;
    // Build batch section, defer to Array.join.
    rs.push(String.fromCodePoint.apply(null, cps.slice(i, e)));
    i = e;
  }
  return rs.join('');
}

var result = codePointsToString(A);
console.log(result.length);

另外,我想要一个奖杯。上面的代码应该在 O(n) 时间内运行并最小化分配的对象数量。不能保证这是“最佳”方法。批处理方法的一个好处,以及为什么包含(或传播调用)的成本,是对中间字符串apply的调用显着减少。String.fromCodePointYMMV - 尤其是跨环境。

这是一个在线基准。所有测试都可以访问和使用由 500k 个元素组成的相同生成的“A”数组。

在此处输入图像描述


推荐阅读