Типизированные массивы в Gecko 2: конкатенация и расширение Float32Array
Я немного смущен Javascript Typed Arrays.
У меня есть несколько Float32Array s, которые не имеют метода concat. Я не знаю, сколько их заранее, кстати.
Я хотел бы объединить их все внутри другого Float32Array, но:
- как я уже говорил, нет метода конкатенации
- Если я попытаюсь написать прошлую длину массива, массив не будет расширен (иначе это не сработает - обратите внимание, что event.frameBuffer и buffer являются Float32Array и что я не знаю, какая конечная длина моего буфер будет):
var length_now = buffer.length;
for (var i = 0; i < event.frameBuffer.length; i += 1) {
buffer [length_now + i] = event.frameBuffer[i];
}
Единственное решение, которое я нашел, это скопировать Float32Array в регулярный массив, что определенно не то, что я хочу. Как бы вы сделали, stackoverflowers?
Ответы
Ответ 1
Типизированные массивы основаны на буферах массива, которые нельзя динамически изменять, поэтому запись за конец массива или использование push()
невозможно.
Один из способов добиться того, что вы хотите, - это выделить новый Float32Array
, достаточно большой, чтобы содержать как массивы, так и выполнить оптимизированную копию:
function Float32Concat(first, second)
{
var firstLength = first.length,
result = new Float32Array(firstLength + second.length);
result.set(first);
result.set(second, firstLength);
return result;
}
Это позволит вам написать:
buffer = Float32Concat(buffer, event.frameBuffer);
Ответ 2
Или, если вы пытаетесь присоединиться к массивам N:
// one-liner to sum the values in an array
function sum(a){
return a.reduce(function(a,b){return a+b;},0);
}
// call this with an array of Uint8Array objects
function bufjoin(bufs){
var lens=bufs.map(function(a){return a.length;});
var aout=new Uint8Array(sum(lens));
for (var i=0;i<bufs.length;++i){
var start=sum(lens.slice(0,i));
aout.set(bufs[i],start); // copy bufs[i] to aout at start position
}
return aout;
}
Ответ 3
У меня была такая же проблема, вы можете добавить к прототипу следующее
Float32Array.prototype.concat = function() {
var bytesPerIndex = 4,
buffers = Array.prototype.slice.call(arguments);
// add self
buffers.unshift(this);
buffers = buffers.map(function (item) {
if (item instanceof Float32Array) {
return item.buffer;
} else if (item instanceof ArrayBuffer) {
if (item.byteLength / bytesPerIndex % 1 !== 0) {
throw new Error('One of the ArrayBuffers is not from a Float32Array');
}
return item;
} else {
throw new Error('You can only concat Float32Array, or ArrayBuffers');
}
});
var concatenatedByteLength = buffers
.map(function (a) {return a.byteLength;})
.reduce(function (a,b) {return a + b;}, 0);
var concatenatedArray = new Float32Array(concatenatedByteLength / bytesPerIndex);
var offset = 0;
buffers.forEach(function (buffer, index) {
concatenatedArray.set(new Float32Array(buffer), offset);
offset += buffer.byteLength / bytesPerIndex;
});
return concatenatedArray;
};
теперь вы можете просто сделать
var array1 = new Float32Array(10000000),
array2 = new Float32Array(10000000);
var array3 = array1.concat(array2);