ショートコードの備忘録

//引数の型を返す
const typeOf=arg=>Object.prototype.toString.call(arg).slice(8,-1);

 //Ajaxでファイルを読み込み文字のエンコードをして返す
const fileLoader=async(path,enc)=>new TextDecoder(enc).decode(await(await fetch(path)).arrayBuffer());

//Ajaxでjsonファイルを得る
const Ajax=async(path,prm={})=>(await(await fetch(path,{method:'post',body:JSON.stringify(prm)}))).json();

//urlのクエリーをobject型にして返す
const getURLQuery=(url=window.location)=>Object.fromEntries(new URLSearchParams(url.search));

//配列をOPTION要素に変換して追加
const appendOption=(elm,ary)=>elm.append(...ary.map(args=>new Option(...args)));

//配列をOPTION要素に変換して置き換える
const replaceSelect=(elm,ary)=>elm.replaceChildren(...ary.map(args=>new Option(...args)));


//配列をテーブルにする
const ary2tbody=(a,b=document.createElement('tbody'))=>a.reduce((b,a)=>(a.reduce((c,d)=>(c.insertCell().append(d),c),b.insertRow()),b),b);
/*
function ary2tbody (ary, tb = document.createElement('tbody')) {
  return ary.reduce((tb, a)=>(a.reduce((tr, str)=>(tr.insertCell().textContent = str, tr),tb.insertRow()), tb), tb);
}
*/
//配列をテーブルにする  Type2
//セルに rowSpan, colSpan, {className: red} が指定できるやつ
/* exp
#!r2c3{className:red} text, text2
text3, text4
....
*/
//
  ary2thead=(a=[],b=document.createElement('thead'))=>{
  let A='^(#)?(?:!(?=[rc\\{])(?:r([2-9]|[1-9]\\d+)|r[01]|r0\\d+)?(?:c([2-9]|[1-9]\\d+)|c[01]|c0\\d+)?(?:\\{(.+)?\\})?)?\\s*(.*)\\s*$',B=RegExp,C=Object;  
  a.map(c=>{b.insertRow().append(...c.map(d=>{let[,z,y,x,w,v]=(new B(A,'i')).exec(d)??[],u={rowSpan:y,colSpan:x,textContent:v};
  C.entries(u).map(a=>a[1]===undefined&&delete u[a[0]]);for(let a,b=new B('\\s*(.+?)\\s*\\:\\s*(.*?)\\s*(,|;|$)','g');a=b.exec(w);u[a[1]]=a[2]);
  return C.assign(document.createElement(z?'th':'td'),u)}))});return b};
//テキストを配列にする
 const csv2ary = csv => csv.split (/r\n|\r|\n/g).reduce ((a,b)=>b.trim()?[...a,b]:a,[]).map (row=> row.split (/\t/g));




//配列の転置(XとYを交換)
const transpose=a=>a[0].map((_,i)=>a.map(b=>b[i]));


//配列の回転(時計回り)
//const rotateRight a=> a[0].map((_,i)=>a.map(b=>b[i]).reverse());
const rotateRight = a=> a[0].map((_,i)=>a.reduceRight((b,c)=>[...b,c[i]],[]));


//配列の回転(180度)
//const inversion =a=> [...a].reverse().map(b=>[...b].reverse());
//const inversion =a=> a.slice().reverse().map(b=>b.slice().reverse());
//const inversion =a=> a.reduceRight((b,c)=>[...b,[...c].reverse()],[]);
const inversion = a=>a.reduceRight((b,c)=>[...b,c.reduceRight((d,e)=>[...d,e],[])],[]);


//配列の回転(反時計回り)
const rotateLeft = a=> a[0].reduceRight((b,_,i)=>[...b,a.map(c=>c[i])],[]);



//組合わせ c= 1:重複あり, 0:重複なし
const permutations=((F=(a=[],b=a.length,c=1)=>2>b?a.map(d=>[d]):a.flatMap((d,e,[...f])=> F((f.splice(e,1-c),f),b-1,c).map(a=>[d,...a])))=>F)();

//順列 c= 1:重複あり, 0:重複なし
const combinations=((f=(a=[],b=a.length,c=1)=>2>b?a.map(d=>[d]):a.flatMap((d,e)=>f(a.slice (e+1-c),b-1,c).map(a=>[d,...a])))=>f)();


//
class P2{
  constructor(x=0,y=0){this.x=x;this.y=y}
  get clone(){return new this.constructor(this.x, this.y)}//複写
  get toArray(){return[this.x,this.y]}//単純配列化
  add({x=0,y=0},{x:X,y:Y}=this){this.x=X+x;this.y=Y+y;return this}//加算
  sub({x=0,y=0},{x:X,y:Y}=this){this.x=X-X;this.y=Y-y;return this}//減算
  mul({x=0,y=0},{x:X,y:Y}=this){this.x=X*x;this.y=Y*y;return this}//乗算
  div({x=0,y=0},{x:X,y:Y}=this){this.x=X/x;this.y=Y/y;return this}//除算
  sMul(n=0,{x:X,y:Y}=this){this.x=X*n;this.y=Y*n;return this}//スカラー倍
}

class V2 extends P2{
  constructor(...p){super(...p)}
  get length(){return(this.x**2+this.y**2)**.5}//長さ
  get negate(){this.x=-this.x;this.y=-this.y;return this}//逆向き
  get normalize(){let L=1/(this.length||1);this.x*=L;this.y*=L;return this}//単位化
  get angle(){return Math.atan2(-this.y,-this.x)+Math.PI}//原点を基準にした角度
  dot({x=0,y=0},{x:X,y:Y}=this){return X*x+Y*y}//ドット積
  cross({x=0,y=0},{x:X,y:Y}=this){return X*y-Y*x}//クロス積
  rotation(a){let m=Math,s=m.sin(a),c=m.cos(a),{x,y}=this;this.x=x*c+y*s;this.y=x*-s+y*c;return this}//回転
}


class P3{
  constructor(x=0,y=0,z=0){this.x=x,this.y=y,this.z=z}
  get clone(){return new this.constructor(this.x,this.y,this.z)}//複写
  get toArray(){return[this.x,this.y,this.z]}//単純配列化
  add({x=0,y=0,z=0},{x:X,y:Y,z:Z}=this){this.x=X+x;this.y=Y+y;this.z=Z+z;return this}//加算
  sub({x=0,y=0,z=0},{x:X,y:Y,z:Z}=this){this.x=X-x;this.y=Y-y;this.z=Z-z;return this}//減算
  mul({x=0,y=0,z=0},{x:X,y:Y,z:Z}=this){this.x=X*x;this.y=Y*y;this.z=Z*z;return this}//乗算
  div({x=0,y=0,z=0},{x:X,y:Y,z:Z}=this){this.x=X/x;this.y=Y/y;this.z=Z/z;return this}//除算
  sMul(n=0,{x:X,y:Y,z:Z}=this){this.x=X*n;this.y=Y*n;this.z=Z*n;return this}//スカラー倍
  applyQuaternion({x=0,y=0,z=0,w=1},{x:X,y:Y,z:Z}=this){//クオータニオンの適用
    let a=w*X+y*Z-z*Y,b=w*Y+z*X-x*Z,c=w*Z+x*Y-y*X,d=-x*X-y*Y-z*Z;
    return this.x=a*w+d*-x+b*-z-c*-y,this.y=b*w+d*-y+c*-x-a*-z,this.z=c*w+d*-z+a*-y-b*-x,this;
  }
  rotation(a=0,b=0,c=0){//ロール、ピッチ、ヨウ
    let {sin:S,cos:C,PI}=Math,{x,y,z}=this,d=PI/180,e=a*d,f=b*d,g=c*d,h=S(e),i=S(f),j=S(g),k=C(e),l=C(f),m=C(g);
    this.x=x*k*l+y*(k*i*j-h*m)+z*(k*i*m+h*j);this.y=x*h*l+y*(h*i*j+k*m)+z*(h*i*m-k*j);this.z=x*-i+y*l*j+z*l*m;return this;
  }
}

class Vector extends P3{
  constructor(...p){super(...p)}
  get length(){return(this.x**2+this.y**2+this.z**2)**.5}//長さ
  get clone(){return new this.constructor(this.x,this.y,this.z)}//複写
  get negate(){return this.sMul(-1)}//逆向き
  get normalize(){return this.sMul(1/(this.length||1))}//単位化
  dot({x=0,y=0,z=0},{x:X,y:Y,z:Z}=this){return X*x+Y*y+Z*z}
	cross ({x=0,y=0,z=0},{x:X,y:Y,z:Z}=this){return this.x=y*Z-z*Y,this.y=z*X-x*Z,this.z=x*Y-y*X,this}
  rotation (a=0,b=0) {//ピッチ、ロール
    let {sin:S,cos:C,PI}=Math,{x,y,z}=this,d=PI/360,e=a*d,f=b*d,g=S(e),h=S(f),
    A=(new Vector(-z,0,(!z&&!x?1:x)).normalize),B=(new Vector(x,y,z).normalize);
    return this.applyQuaternion(new Quaternion(A.x*g,A.y*g,A.z*g,C(e))).applyQuaternion(new Quaternion(B.x*h,B.y*h,B.z*h,C(f)));
  }
}

//__________________________

class Quaternion{
  constructor (x=0,y=0,z=0,w=1){this.x=x;this.y=y;this.z=z;this.w=w}
  get clone(){return new this.constructor(this.x,this.y,this.z,this.w)}//複写
  get length(){return(this.x**2+this.y**2+this.z**2+this.w**2)**.5}
	get normalize(){let L=this.length;return (L?(L=1/L,this.x*=L,this.y*=L,this.z*=L,this.w*=L):this.x=this.y=this.z=0,this.w=1),this}
  dot({x=0,y=0,z=0,w=1},{x:X,y:Y,z:Z,w:W}=this){return X*x+Y*y+Z*z+W*w}
  mul({x=0,y=0,z=0,w=1},{x:X,y:Y,z:Z,w:W}=this){return this.x=X*w+W*x+Y*z-Z*y,this.y=Y*w+W*y+Z*x-X*z,this.z=Z*w+W*z+X*y-Y*x,this.w=W*w-X*x-Y*y-Z*z,this}
  add({x,y,z,w}){return this.x+=x,this.y+=y,this.z+=z,this.w+=w,this}
  setFromAxisAngle(a=0,_){this.w*=Math.cos(_=a/2);this.x*=(_=Math.sin(_));this.y*=_;this.z*=_;return this}
}

//______________________________________________________________

//template要素を雛型として配列をデータにする
function deriveFromTemplate (template, recs = [ ]) {
  let tp = ('TEMPLATE' === template.tagName)
           ? template.content.cloneNode (true)
           : template.cloneNode (true);
  let es = [...tp.querySelectorAll ('*[name]')];
  let rst = [ ];
  
  for (let rec of recs) {
    for (let e of es) {
      let name = e.name;
      if (rec.hasOwnProperty (name)) {
        let val = rec[name];
        e.value = (val != null) ? val: '';
      }
    }
    rst.push (tp.cloneNode (true));
  }
  return rst;
}


//template要素から前方の要素を削除する
function replaceBeforeFromTemplate (template, elements = [ ]) {
  if ('TEMPLATE' !== template.tagName)
    throw new Error ();
  
  for (let e; e = template.previousElementSibling; ) {
    if ('TEMPLATE' === e.tagName)
      break;
    e.remove ();
  }
  if (elements.length)
    template.before (...elements);
}


//template要素から後方の要素を削除する
function replaceAfterFromTemplate (template, elements = [ ]) {
  if ('TEMPLATE' !== template.tagName)
    throw new Error ();
  
  for (let e; e = template.nextElementSibling; ) {
    if ('TEMPLATE' === e.tagName)
      break;
    e.remove ();
  }
  if (elements.length)
    template.after (...elements);
}


//数値を漢数字に変換する
function kansuji(a,t=0,r='',N=[...'〇一二三四五六七八九'],M=['',...'十百千'],K=['',...'万億兆京垓𥝱穣溝澗']){
  return(''+a).replace(/(\d+)/g,a=>{
    if(t||'0'==a)return[...a].map(n=>N[n]).join``;
    [...a].reverse().map((n,i)=>r=(((n-=0)==1&&i%4||!n)?'': N[n])+M[i%4]+(i%4?r:K[(i/4)|0]+r))
    return r;
  })
}