web-dev-qa-db-fra.com

Comment puis-je fusionner TypedArrays en JavaScript?

Je voudrais fusionner plusieurs tampons de tableau pour créer un objet blob. cependant, comme vous le savez, TypedArray n'a pas de "Push" ou de méthodes utiles ...

Par exemple.:

var a = new Int8Array( [ 1, 2, 3 ] );
var b = new Int8Array( [ 4, 5, 6 ] );

Par conséquent, j'aimerais obtenir [ 1, 2, 3, 4, 5, 6 ].

40
yomotsu

Utilisez la méthode set. Mais notez que vous avez maintenant besoin du double de mémoire!

var a = new Int8Array( [ 1, 2, 3 ] );
var b = new Int8Array( [ 4, 5, 6 ] );

var c = new Int8Array(a.length + b.length);
c.set(a);
c.set(b, a.length);

console.log(a);
console.log(b);
console.log(c);
70
Prinzhorn

J'utilise toujours cette fonction:

function mergeTypedArrays(a, b) {
    // Checks for truthy values on both arrays
    if(!a && !b) throw 'Please specify valid arguments for parameters a and b.';  

    // Checks for truthy values or empty arrays on each argument
    // to avoid the unnecessary construction of a new array and
    // the type comparison
    if(!b || b.length === 0) return a;
    if(!a || a.length === 0) return b;

    // Make sure that both typed arrays are of the same type
    if(Object.prototype.toString.call(a) !== Object.prototype.toString.call(b))
        throw 'The types of the two arguments passed for parameters a and b do not match.';

    var c = new a.constructor(a.length + b.length);
    c.set(a);
    c.set(b, a.length);

    return c;
}

La fonction d'origine sans vérification de null ou de types

function mergeTypedArraysUnsafe(a, b) {
    var c = new a.constructor(a.length + b.length);
    c.set(a);
    c.set(b, a.length);

    return c;
}
7
Dänu

pour la solution côté client ~ ok:

const a = new Int8Array( [ 1, 2, 3 ] )
const b = new Int8Array( [ 4, 5, 6 ] )
const c = Int8Array.from([...a, ...b])
4
JerryCauser

J'aime la réponse de @ prinzhorn mais je voulais quelque chose d'un peu plus flexible et compact:

var a = new Uint8Array( [ 1, 2, 3 ] );
var b = new Float32Array( [ 4.5, 5.5, 6.5 ] );

const merge = (tArrs, type = Uint8Array) => {
  const ret = new (type)(tArrs.reduce((acc, tArr) => acc + tArr.byteLength, 0))
  let off = 0
  tArrs.forEach((tArr, i) => {
    ret.set(tArr, off)
    off += tArr.byteLength
  })
  return ret
}

merge([a, b], Float32Array)
0
mattdlockyer

Comme une ligne, qui prendra un nombre arbitraire de tableaux (myArrays ici) et de types mixtes tant que le type de résultat les prend tous (Int8Array ici):

let combined = Int8Array.from(Array.prototype.concat(...myArrays.map(a => Array.from(a))));
0
randomsock

si j'ai plusieurs tableaux tapés

            arrays = [ typed_array1, typed_array2,..... typed_array100]

Je veux concaténer tous les 1 à 100 sous-tableaux en un seul "résultat", cette fonction fonctionne pour moi.

  single_array = concat(arrays)


function concat(arrays) {
  // sum of individual array lengths
  let totalLength = arrays.reduce((acc, value) => acc + value.length, 0);

  if (!arrays.length) return null;

   let result = new Uint8Array(totalLength);

      // for each array - copy it over result
      // next array is copied right after the previous one
      let length = 0;
      for(let array of arrays) {
            result.set(array, length);
            length += array.length;
      }

      return result;
   }
0
hoogw