将较大的字节数组转换为字符串
当
N
设置为
125K
时,以下操作有效
let N = 125000
let x = [...Array(N)].map(( xx,i) => i)
let y = String.fromCodePoint(...x)
console.log(y.length)
当 N 设置为
128K
时,相同的代码会中断:
Uncaught RangeError: Maximum call stack size exceeded
这是一个常见操作:实现转换的最佳方法是什么?
请注意,我确实查看了相关的问答。
https://stackoverflow.com/a/3195961/1056563
我们不应该依赖
node.js
,而且使用
fromCharCode.apply
的方法也失败了。最后,这个答案已经有近十年了。
那么,处理这种转换的最新、最有效的方法是什么呢?
问题是由于
实现
对
接受的参数数量
有
限制
。当通过扩展运算符向
String.fromCodePoint
函数提供过多参数(在本例中超过 ~128k)时,会导致引发异常。
虽然代码量略多,但
相对高效
解决此问题的一种方法是跨多个调用批量执行操作。这是我提议的实现,它修复了我认为与扩展性能
和
代理对
的处理有关的问题(这是不正确的:
fromCodePoint
不关心代理,因此在这种情况下它比
fromCharCode
更可取)。
957188​​596
另外,我想要一个奖杯。上面的代码应该在 O(n) 时间内运行,并尽量减少分配的对象数量。不能保证这是“最佳”方法。批处理方法的一个好处,以及为什么
apply
(或扩展调用)的成本被纳入,是
String.fromCodePoint
和中间字符串的调用次数显着减少。 YMMV - 尤其是在不同环境中。
这是一个 在线基准 。所有测试都可以访问并使用相同的生成的 500k 个元素的“A”数组。
给出的答案性能不佳:我测量了其中一个答案的 19 秒,其他答案也差不多 (*)。必须 预分配 输出数组。接下来是 20 到 40 毫秒 秒。快了三个数量级。
function wordArrayToByteArray(hash) {
var result = [...Array(hash.sigBytes)].map(x => -1)
let words = hash.words
//map each word to an array of bytes
.map(function (v) {
// create an array of 4 bytes (less if sigBytes says we have run out)
var bytes = [0, 0, 0, 0].slice(0, Math.min(4, hash.sigBytes))
// grab that section of the 4 byte word
.map(function (d, i) {
return (v >>> (8 * i)) % 256;
})
// flip that
.reverse()
;
// remove the bytes we've processed
// from the bytes we need to process
hash.sigBytes -= bytes.length;
return bytes;
})
words.forEach((w,i) => {
result.splice(i * 4, 4, ...w)
})
result = result.map(function (d) {
return String.fromCharCode(d);
}).join('')
return result
}
(*) 除了 @User2864740 可能例外 - 我们正在等待他的数字。但他的解决方案也在循环内使用了
apply()
,这导致相信它也会很慢。
“老式” JavaScript:
var N=125000;
var y="";
for(var i=0; i<N; i++)
y+=String.fromCharCode(i);
console.log(y.length);
使用 N=1000000