1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

2次元TypedArrayの平坦化

Last updated at Posted at 2024-11-03

現時点でTypedArrayに2次元は実装されていませんが、ArrayTypedArrayを詰め込んだ2次元風TypedArrayを作る事はよくあります。…ないですか? ならばよし!
さて本題、2次元もどきを1次元に変換する処理を考察してみます

let a=[new Uint8Array([1]), new Uint8Array([2,3]), new Uint8Array([4,5,6])],
b=a.flat()

上記のような処理ではbはArrayとなり、TypedArrayではありません。素朴なloopで実現してみましょう。A.reduce((a,b)=>a+b.length,0)で要素総数を調べてTypedArrayに突っ込みます

let A=[new Uint8Array([1]), new Uint8Array([2,3]), new Uint8Array([4,5,6])],
	B=new Uint8Array(A.reduce((a,b)=>a+b.length,0)),b=0;
for(let a of A)B.set(a,b),b+=a.length;
console.log(B)//[1,2,3,4,5,6]

Blobを利用すると簡単です。ただしasyncやらawaitやら必要になるのが難点。非同期のnew Blob(a).arrayBuffer().then(a=>{...})で代用するのもいい

8bits
(async a=>{
//2次元もどきTypedArray
a=[new Uint8Array([1]), new Uint8Array([2,3]), new Uint8Array([4,5,6])];
//1次元化
a=new Uint8Array(await new Blob(a).arrayBuffer());
console.log(a)//[1,2,3,4,5,6]
})()
16bits
(async a=>{
a=[new Uint16Array([1]), new Uint16Array([11,111]), new Uint16Array([1111,11111,-1])];
a=new Uint16Array(await new Blob(a).arrayBuffer())
console.log(a)//[1,11,111,1111,11111,65535]
})()

速度比較

速度性能はどうなのでしょうか。loopの方はreduce + for of版とfor of x 2版を用意。Blob版は前述と同様。

const flat0=A=>{
	let B=new Uint8Array(A.reduce((a,b)=>a+b.length,0)),b=0;
	for(let a of A)B.set(a,b),b+=a.length;
	return B
},
flat1=A=>{let a,b=0,B;
	for(a of A)b+=a.length;
	B=new Uint8Array(b);b=0;
	for(a of A)B.set(a,b),b+=a.length;
	return B
},
flat2=async A=>new Uint8Array(await new Blob(A).arrayBuffer());

(async()=>{console.clear();
for(let loop=1<<18,size=1024,n=8;n--;loop>>=1,size*=2){
	let A=Array(loop).fill(new Uint8Array(size));
	console.time("loop0");
	flat0(A);
	console.timeEnd("loop0");
	console.time("loop1");
	flat1(A);
	console.timeEnd("loop1");
	console.time("blob");
	await flat2(A);
	console.timeEnd("blob");
}})()

Blobが他を圧倒する低速ぶりでした。5倍以上遅いですよフフフ…。想定外の結果と言わざるを得ません。flat0とflat1は同程度ですが、flat0(reduce版)は配列が極端に小さい場合不利っぽいですよフフフ…。

番外編

以下の処理では何が出力されるでしょうか? 3,3,3? 1,2,3?

let a=[Array(1),Array(2),Array(3)];
for(a of a)console.log(a.length)

なぜこんな問題出したか…。それは本記事は当初こんな書き方をしようとしていたからだ! 混乱を避けるために改変したらしい…

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?