2016-06-29 49 views
10

Nel momento in cui mi trovo bloccato cercando di appiattire un Uint8ClampedArray.Come appiattire un array bloccato

La struttura di matrice iniziale è data = [227, 138, 255…] e dopo aver creato una matrice da quella di tipo enc = [Uint8ClampedArray[900], Uint8ClampedArray[900], Uint8ClampedArray[900]...], provo ad appiattirla.

Ho provato molti metodi/soluzioni per questo, ma nessuno sembra funzionare:

MDN metodo

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) { 
    return a.concat(b); 
}, []); 

suggerito con concat

data = [].concat.apply([], enc); 

e attraverso una funzione

function flatten(arr) { 
    return arr.reduce(function (flat, toFlatten) { 
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten); 
    }, []); 
} 

ma nessuna gioia fino ad ora, continua a restituire l'array così com'è. Chiunque può indicarmi la giusta direzione e spiegare perché è così?

-EDIT- Bottom line: ho bisogno di restituire un oggetto Array regolare, come quello di partenza non digitato.

risposta

3

Se enc è un Array di Uint8ClampedArray s, questa affermazione one-liner dovrebbe funzionare:

var flattened = Uint8ClampedArray.from(enc.reduce((a, b) => [...a, ...b], [])); 

Ciò equivale a:

var flattened = Uint8ClampedArray.from(enc.reduce(function(a, b){ 
    return Array.from(a).concat(Array.from(b)); 
}, [])); 

per rispondere alla tua domanda effettiva sul perché reduce non ha funzionato per voi:

[].concat(Uint8ClampedArray([1, 2, 3, 4])); 

purtroppo non restituisce [1, 2, 3, 4] ma [Uint8ClampedArray[4]]. concat non funziona con matrici tipizzate.

+0

Ma questo converte le matrici tipizzate in un array normale (prima di convertirle in un array tipizzato). Qual è il punto di utilizzo degli array digitati, quindi? – Oriol

2

Il controllo di MDN, TypedArray s non condivide alcune normali funzioni di array JS.

è possibile raccogliere i valori dalla matrice bloccato, e inizializzare un nuovo uno come questo però:

var enc = [Uint8ClampedArray.of(1, 2), Uint8ClampedArray.of(4, 8), Uint8ClampedArray.of(16, 32)] 

var flattened = Uint8ClampedArray.from(enc.reduce(function(acc, uintc){ 
    Array.prototype.push.apply(acc, uintc) 
    return acc; 
}, [])); 

console.log(flattened); // [object Uint8ClampedArray] 
console.log(flattened.join(',')); // "1,2,4,8,16,32" 
+0

Questo sembra funzionare, anche se era un po 'di confusione su ciò che 'a' è dovrebbe essere. Se sostituito da 'enc', funziona. – Xufox

+0

Ho dimenticato di copiare il mio array di test, che è stato chiamato 'a'; – kazenorin

+0

Ma questo converte gli array digitati in un array normale (prima di convertirlo in un array tipizzato). Qual è il punto di utilizzo degli array digitati, quindi? – Oriol

4

Vorrei calcolare prima la lunghezza totale e quindi utilizzare set. Il vantaggio di set è

Se la matrice di origine è una matrice tipizzata, le due matrici possono condividere la stessa ArrayBuffer sottostante; il browser copierà in modo intelligente l'intervallo di origine del buffer nell'intervallo di destinazione.

function flatten(arrays, TypedArray) { 
 
    var arr = new TypedArray(arrays.reduce((n, a) => n + a.length, 0)); 
 
    var i = 0; 
 
    arrays.forEach(a => { arr.set(a,i); i += a.length; }); 
 
    return arr; 
 
} 
 
console.log(flatten(
 
    [new Uint8ClampedArray([1,2,3]), new Uint8ClampedArray([4,5,6])], 
 
    Uint8ClampedArray 
 
));

Un'alternativa sta usando macchie, come proposed by guest271314.Il modo corretto sarebbe

function flatten(arrays, TypedArray, callback) { 
 
    var reader = new FileReader(); 
 
    reader.onload =() => { 
 
    callback(new TypedArray(reader.result)); 
 
    }; 
 
    reader.readAsArrayBuffer(new Blob(arrays)); 
 
} 
 
flatten(
 
    [new Uint8ClampedArray([1,2,3]), new Uint8ClampedArray([4,5,6])], 
 
    Uint8ClampedArray, 
 
    result => console.log(result) 
 
);

1

Modifica, aggiornato

firefox, ogni notte restituisce attualmente [[object Uint8ClampedArray],[object Uint8ClampedArray],[object Uint8ClampedArray]] a FileReader()result come sottolineato da @Oriol.

Un approccio usando spread element, rest element, for..of, che restituisce gli stessi risultati come il cromo, cromo utilizzando Blob(), FileReader(); TextEncoder(), TextDecoder(); JSON.parse() avvicina

var enc = [new Uint8ClampedArray(900) 
 
      , new Uint8ClampedArray(900) 
 
      , new Uint8ClampedArray(900)]; 
 

 
var res = []; 
 
for (let prop of enc) [...res] = [...res, ...prop]; 
 

 
console.log(res);

o, più breve, come suggerito da @Oriol

var res = []; 
var enc = [new Uint8ClampedArray(900), new Uint8ClampedArray(900)]; 
for (let prop of enc) res.push(...prop); 

È possibile utilizzare Blob() che concatena i parametri in un'unica Blob oggetto, FileReader(), JSON.parse()

var enc = [new Uint8ClampedArray(900) 
 
      , new Uint8ClampedArray(900) 
 
      , new Uint8ClampedArray(900)]; 
 

 
var blob = new Blob([enc]); 
 

 
var reader = new FileReader(); 
 
reader.onload =() => { 
 
    console.log(JSON.parse("[" + reader.result + "]")) 
 
} 
 
reader.readAsText(blob);

in alternativa, utilizzando TextEncoder(), TextDecoder(), JSON.parse()

var enc = [new Uint8ClampedArray(900) 
 
      , new Uint8ClampedArray(900) 
 
      , new Uint8ClampedArray(900)]; 
 

 
var encoder = new TextEncoder(); 
 
var arr = encoder.encode(enc); 
 
var decoder = new TextDecoder(); 
 
var res = JSON.parse("[" + decoder.decode(arr) + "]"); 
 
console.log(res);

+0

Sì, questa è una soluzione che ho facilmente capito perché ho lavorato con Blob prima. – iomv

+2

[Questo non funziona su Firefox] (http://i.stack.imgur.com/rQZGc.png). 'JSON.parse: carattere inatteso' – Oriol

+0

@Oriol Puoi descrivere" non funziona "? 'JSON.parse: carattere inatteso' Non ha ricevuto errori, qui, ad entrambi gli approcci. Puoi creare un jsfiddle o un plnkr per dimostrare? In alternativa puoi usare '.split (/, /). Map (Number)'. Quale sarebbe il personaggio inaspettato? – guest271314