2016-06-29 28 views
10

In der Minute finde ich mich stecken, versuchend, ein Uint8ClampedArray zu glätten.Wie man eine festgeklemmte Anordnung abflacht

Die Start-Array-Struktur ist data = [227, 138, 255…] und nach dem Erstellen eines Arrays aus dem ähnlichen enc = [Uint8ClampedArray[900], Uint8ClampedArray[900], Uint8ClampedArray[900]...] ich versuche, es zu glätten.

Ich habe versucht, viele Methoden/Lösungen für das, aber niemand scheint zu funktionieren:

die MDN Methode vorgeschlagen

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

mit concat

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

und durch eine Funktion

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

aber bisher keine Freude, es hält das Array so wie es ist. Jeder kann mich in die richtige Richtung weisen und erklären, warum ist das so?

-EDIT- Bottom line: Ich brauche es, um ein reguläres Array-Objekt zurückzugeben, wie die nicht typisierte Startobjekt.

Antwort

3

Wenn enc ein Array von Uint8ClampedArray s ist, diese Einzeiler Aussage sollte funktionieren:

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

Dies ist äquivalent zu:

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

Um Ihre aktuelle Frage zu beantworten, warum reduce nicht für Sie arbeiten:

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

leider nicht [1, 2, 3, 4] aber [Uint8ClampedArray[4]] zurückgibt. concat funktioniert nicht mit typisierten Arrays.

+0

Aber das konvertiert die typisierten Arrays in ein normales Array (bevor es wieder in ein typisiertes Array konvertiert wird). Worauf kommt es an, typisierte Arrays zu verwenden? – Oriol

2

Überprüfen der MDN, TypedArray s teilt nicht einige normale JS-Array-Funktionen.

Sie können die Werte aus dem geklemmten Array sammeln, und einen neuen, ähnlichen jedoch initialisieren:

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

Dies scheint zu funktionieren, obwohl es ein wenig verwirrend zu war, was 'a' ist soll sein. Wenn es durch 'enc' ersetzt wird, funktioniert es. – Xufox

+0

Ich habe vergessen, mein Test-Array zu kopieren, das 'a' genannt wurde; – kazenorin

+0

Aber dies konvertiert die typisierten Arrays in ein normales Array (bevor es wieder in ein typisiertes Array konvertiert wird). Worauf kommt es an, typisierte Arrays zu verwenden? – Oriol

4

Ich würde zuerst die Gesamtlänge berechnen und dann set verwenden. Der Vorteil ist set

Wenn das Quellenarray eine typisierte Array ist, wobei die beiden Anordnungen können die gleichen zugrunde liegenden Arraybuffer teilen; Der Browser kopiert den Quellbereich intelligent in den Zielbereich.

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 
 
));

Eine Alternative ist mit Blobs, wie proposed by guest271314.Der richtige Weg wäre

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

bearbeiten,

Aktualisiert

firefox, nächtliche derzeit gibt [[object Uint8ClampedArray],[object Uint8ClampedArray],[object Uint8ClampedArray]] bei FileReader()result wie erwähnt durch @Oriol.

Ein Ansatz unter Verwendung von spread element, rest element, for..of, die gleichen Ergebnisse wie Chrom zurückgibt, Chrom Blob() Verwendung FileReader(); TextEncoder(), TextDecoder(); JSON.parse() nähert sich

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

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

 
console.log(res);

oder kürzer, wie von @Oriol

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

Sie Blob() verwenden können, welche Parameter in einzelne Blob Objekt verkettet, 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);

alternativ mit 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

Ja, das ist eine Lösung, die ich leicht verstehe, weil ich vorher mit Blobs gearbeitet habe. – iomv

+2

[Dies funktioniert nicht mit Firefox] (http://i.stack.imgur.com/rQZGc.png). 'JSON.parse: Unerwartetes Zeichen' – Oriol

+0

@Oriol Kannst du" funktioniert nicht "beschreiben? 'JSON.parse: Unerwartetes Zeichen' Bei beiden Methoden wurde hier kein Fehler angezeigt. Kannst du ein jsfiddle oder ein plnkr erstellen, um es zu demonstrieren? Sie könnten alternativ '.split (/, /). Map (Number)' verwenden. Was wäre unerwarteter Charakter? – guest271314