SELECTの連携を今更ながら書いてみた
寺尾で答えてみた
https://teratail.com/questions/310078
なぜか面白くない。
提示されたコードは見難い。なので最初から自分で好きなように書いた方が楽。
汚いコードを指摘してあげるより、私はこれが楽だ。
本当の意味でのショートコーディングは奥が深い。
オブジェクト指向の書き方も奥が深い。
アンカータグの name 属性は無くなっていたのか!知らなかった。
ちょっとだけ賢くなった。
<!DOCTYPE html> <html lang="ja"> <meta charset="UTF-8"> <title>連携SELECT</title> <style> li > ol { margin: 0; padding: 0; } </style> <body> <ol> <li>第一選択肢 <p> <select name="cat1"> <option value="" selected>選択してください</option> <option value="0">a</option> <option value="1">b</option> </select> </p> <li>第二選択肢 <ol> <li> <select name="cat2"> <option value="">選択してください</option> <option value="0">a-a</option> <option value="1">a-b</option> </select> <li> <select name="cat2"> <option value="">選択してください</option> <option value="2">b-a</option> <option value="3">b-b</option> </select> </ol> <li>第三選択肢 <ol> <li> <select name="cat3"> <option value="">選択してください</option> <option value="1">a-a-a</option> <option value="2">a-a-b</option> </select> <li> <select name="cat3"> <option value="">選択してください</option> <option value="3">a-b-a</option> <option value="4">a-b-b</option> </select> <li> <select name="cat3"> <option value="">選択してください</option> <option value="5">b-a-a</option> <option value="6">b-a-b</option> </select> <li> <select name="cat3"> <option value="">選択してください</option> <option value="7">b-b-a</option> <option value="8">b-b-b</option> </select> </ol> <li id="cat4">結果 <ol> <li>まだ全て選択されていません</li> <li><a href="exp.co.jp#a-a-a">a-a-a</a> <li><a href="exp.co.jp#a-a-b">a-a-b</a> <li><a href="exp.co.jp#a-b-a">a-b-a</a> <li><a href="exp.co.jp#a-b-a">a-b-b</a> <li><a href="exp.co.jp#b-a-a">b-a-a</a> <li><a href="exp.co.jp#b-a-b">b-a-b</a> <li><a href="exp.co.jp#b-b-a">b-b-a</a> <li><a href="exp.co.jp#a-a-a">b-b-b</a> </ol> </ol> <hr> <ol> <li>第一選択肢 <p> <select name="chk0"> <option value="" selected>選択してください</option> <option value="0">a</option> <option value="1">b</option> </select> </p> <li>第二選択肢 <ol> <li> <select name="chk1"> <option value="">選択してください</option> <option value="http://www.xxx.co.jp#AA">a-a</option> <option value="http://www.xxx.co.jp#AB">a-b</option> </select> <li> <select name="chk1"> <option value="">選択してください</option> <option value="http://www.xxx.co.jp#BA">b-a</option> <option value="http://www.xxx.co.jp#BB">b-b</option> </select> </ol> </ol> <script> class A { constructor (name) { this.name = name; this.reg = new RegExp ('^'+ name + '(\\d+)$'); this.next (document.querySelector (`*[name^="${name}"]`)); } next (e) { let r; if (r = this.reg.exec (e.name)) this.nextStage (this.name + (Number (r[1]) + 1), Number (e.value || "-1")); } nextStage (name, no) { let es = document.querySelectorAll (`*[name="${name}"], #${name}>ol>li`), n = no < 0 ? 0: no; es.forEach ((e, i)=> { if ('select-one' === e.type) { e.disabled = no != i; e.selectedIndex = 0; } let li = e.closest ('li'); if (li) li.style.display = n == i ? 'block': 'none'; }); if (es[0]) this.next (es[0]); } handleEvent ({target: e}) { this.next (e); } } class B { constructor (...select) { this.select = select; } handleEvent ({target: e}) { if (this.select.includes (e) && e.value) if (confirm (e.value + 'に移動します')) location.href = e.value; } } //_____ document.addEventListener ('change', new A ('cat'), false); document.addEventListener ('change', new A ('chk'), false); document.addEventListener ('change', new B (...document.querySelectorAll ('select[name="chk1"]')), false); </script>
PerlinNoise
class PerlinNoise { constructor (random = Math.random) { this.random = random; this.gradient = new Map; } randomGradient (x) { if (! this.gradient.has (x)) this.gradient.set (x, this.random () * 2 -1); return this.gradient.get (x); } noise (x) { let x0 = x |0, x1 = x0 + 1, r0 = x - x0, r1 = r0 - 1, u = r0 * this.randomGradient (x0), v = r1 * this.randomGradient (x1), sx = r0 * r0 * (3 - 2 * r0); return 2 * (u + sx * (v - u)); } }
PHP クラスの覚書
PHP クラスの覚書
<?php /* http://www.tohoho-web.com/php/class.html */ //class の使い方 // 1.定義 class A { //定数の定義 const PI = 3.14; //プロパティの宣言 public $a;//どこからでもアクセスできる protected $b;//クラス自身、継承したクラス、親クラスからアクセスできる private $c;//そのクラス自身だけ参照可 //インスタンス化すると暗黙に最初に呼ばれる function __construct ($a, $b, $c) { $this->a = $a; // 4. $this->b = $b; $this->c = $c; } //以下メソッドの定義... public function dispA () { echo self::PI. "\n";//定数の参照 echo $this-> a; } //final 継承されたものからの上書きを禁止 final public function dispB () { echo $this-> b; } //インスタンス化しない状態で呼び出す static function dispC () { echo "func dispC"; // echo $this-> c; } } // クラスの継承 class B extends A { // 親となる A を継承することを意味する function __construct ($a, $b, $c) { parent::__construct ($a, $b, $c);//明示的に継承元を呼び出す必要あり } //オブジェクト消滅時に呼び出される function __destruct () { parent::__destruct ();//継承元へも呼び出す } public function dispA () { echo $this-> a; //継承もとのメソッドのオーバーライド dsipB は禁止状態 } } $b = new B ('a', 'b', 'c');// 3.インスタンス化する $_a = clone $b; // オブジェクトの複製 $_c = $_a; //参照元が同じなので同等 B::dispC (); //______________________________ //抽象クラス (サブクラスDが必ず定義しなくてはならない抽象メソッドを定義します) abstract class C { abstract public function dispA (); abstract public function dispB (); public function dispC () { echo $this-> a; } } class D extends C { public function dispA () { echo $this-> a; } public function dispB () { echo $this-> b; } } //new C (); #単独でこれはできない new D (); #OK //______________________________ //インタフェース (実装クラスが必ず定義しなくてはならないメソッドを定義します) interface E { public function dispA ($arg);//変数も指定すること public function dispB ($arg, $arg2);//引数の名前は適当でよいが数は合わせる必要あり public function dispC (); } class F implements E { public function dispA ($arg) { echo $this-> a; } public function dispB ($arg0, $arg1) { echo $this-> b; } public function dispC () { echo $this-> c; } } new F (); //______________________________ //タイプヒンティング class A { } class B { public function test (A $arg) { ; } } //______________________________ //オートローディング spl_autoload_register (function ($class_name) { include("{$class_name}.php");//G.php が読み込まれる }); $g = new G(); ?>
MySQL と PHP を経由して、JavaScript にデータを送るための
<?php //_____________________________ //MySQL Driver PDO クラス生成 interface DBDriver { //このクラスを継承させること public function send ($sql, $prm, $type, $multi); } //_____ class MySQL implements DBDriver { const DBNAME = '**********'; //DB名前 const HOST = 'localhost'; //DBホスト名 const USER = 'root'; //DB使用ユーザー名 const PASS = '***********'; //DB暗証番号 //MySQLの設定値(php5.3 では定数として配列が使えない) private static $opt = array ( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //error時のthrowが有効になる PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, //fetch 時の取得方法 PDO::ATTR_EMULATE_PREPARES=>false, PDO::ATTR_PERSISTENT=> true, //接続を維持する PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=> true //バッファを利用する ); //_____ protected $pdo = null;//PDOの実態 //_____ //初回定義時 function __construct ($name= self::DBNAME, $host= self::HOST, $user= self::USER, $pass= self::PASS, $opt= array ()) { try { $option = $opt + self::$opt; //$opt は上書きされない $db = sprintf ('mysql:dbname=%s; host=%s; charset=utf8mb4', $name, $host); $this->pdo = new PDO ($db, $user, $pass, $option); } catch (PDOException $err) {//MySQL でエラー発生 if (DEBUG) { header ('Content-Type: text/plain; charset=UTF-8', true, 403); echo $err; } die (); } catch (Exception $ex) { die (); } } //_____ //送信 public function send ($sql, $prm = null, $type = PDO::FETCH_ASSOC, $multi = true) { $PDO = $this->pdo; try { switch (true) { case (null === $prm) ://パラメータ無し switch ($type) { case 'count' : case 'COUNT' : case NULL: case FALSE : return $PDO-> exec ($sql);//戻り値は作用した行数 case 'id' : case 'ID' : $hd = $PDO-> query ($sql); return $hd ? $PDO-> lastInsertId (): $hd; //結局失敗するとfalse default : $hd = $PDO-> query ($sql); return $multi ? $hd-> fetchAll ($type) : $hd-> fetch ($type) ; } default ://パラメータ有り if (array_values ($prm) !== $prm) $prm = self::addColon ($prm);//連想配列ならコロンを付加 $hd = $PDO-> prepare ($sql); $rst = $hd-> execute ($prm); //戻り値が無い場合 switch ($type) { case 'id': case 'ID' : return $rst ? $PDO-> lastInsertId (): $rst; case 'count' : case 'COUNT' : return $rst ? $hd-> rowCount (): $rst;//失敗は false case NULL : case FALSE : return $rst; default: return $multi ? $hd-> fetchAll ($type) : $hd-> fetch ($type) ; } } } catch (PDOException $err) { if (DEBUG) { header ('Content-Type: text/plain; charset=UTF-8', true, 403); echo $sql."\n"; echo Array_Deployment($prm)."\n"; echo $err-> getMessage ()."\n"; } die(); } } //_____ private function addColon ($ary) { $rst = array (); foreach ($ary as $key => $val) $rst[':'.$key] = $val; return $rst; } } //_____________________________ interface DBTableController { // public function __construct ($pdo, $tb_name, $id_name); public function select ($QUERY); public function update ($RECODE); public function insert ($RECODE); public function delete ($ID_LIST); } class TableRecorder implements DBTableController { private $pdo; private $tb_name; private $id_name; //_____ function __construct (DBDriver $pdo, $tb_name, $id_name = 'ID') { $this->pdo = $pdo; $this->tb_name = $tb_name; $this->id_name = $id_name; } //_____ public function select ($QUERY, $ARG= null, $LIMIT= 0, $OFFSET= 0) { $order = array ('%%TABLE%%', '%%ID%%'); $replace = array ($this->tb_name, $this->id_name); $query = str_replace ($order, $replace, $QUERY); if ($LIMIT) { $query .= ' LIMIT '. strval ($LIMIT); //offsetの生成 if ($OFFSET) $query .= ' OFFSET '. strval ($OFFSET); } $rst = $this->pdo->send ($query, $ARG); return array ( 'data'=> $rst, 'query'=> $query, 'arg'=> $ARG, 'error'=> false === $rst ); } public function length ($QUERY= 'SELECT COUNT(*) FROM %%TABLE%%', $ARG= null) { $rst = $this->pdo->send ($QUERY, $ARG, PDO::FETCH_COLUMN, false); return array ( 'length'=> $rst, 'query'=> $QUERY, 'arg'=> $ARG, 'error'=> false === $rst ); } public function getOffsetID ($ID, $OFFSET= 0) { $query = ($OFFSET > 0) ? 'SELECT %2$s FROM %1$s WHERE %2$s>=:ID ORDER BY %2$s LIMIT 1 OFFSET %3$d' : 'SELECT %2$s FROM %1$s WHERE %2$s<=:ID ORDER BY %2$s DESC LIMIT 1 OFFSET %3$d'; $query = sprintf ($query, $this->tb_name, $this->id_name, abs ($OFFSET)); $rst = $this->pdo->send ($query, array ('ID'=> $ID), PDO::FETCH_COLUMN, false); return array ( 'id'=> $rst, 'query'=> $QUERY, 'offset'=> abs ($ARG), 'error'=> false === $rst ); } //_____ //レコードの更新 public function update ($ID, $RECODE = array ()) { $query = sprintf ( 'UPDATE %1$s SET %4$s WHERE %2$s=%3$s', $this->tb_name, $this->id_name, $ID, self::convNameList ($RECODE) ); $rst = $this->pdo->send ($query, $RECODE, null); return array ( 'id'=> $RECODE[$this->id_name], 'query'=> $query, 'recode'=> $RECODE, 'error'=> false === $rst ); } //_____ //レコードの挿入 public function insert ($RECODE) { $names = array_keys ($RECODE); $query = sprintf ( 'INSERT INTO %s (%s) VALUES(:%s)', $this->tb_name, implode (',', $names), implode (',:', $names) ); $id = count ($RECODE) ? $this->pdo->send ($query, $RECODE, 'id') : false ; return array ( 'id'=> $id, 'query'=> $query, 'error'=> false === $id ); } //_____ //指定されたIDを削除する public function delete ($ID_LIST = array ()) { $query = sprintf ( 'DELETE FROM %s WHERE %s IN (%s)', $this->tb_name, $this->id_name, implode (',', $ID_LIST)//IDを整数限定にしている? ); $cnt = count ($ID_LIST) ? $this->pdo->send ($query, null, 'count') : false; return array ( 'count'=> $cnt, 'query'=> $query, 'id'=> $ID_LIST, 'error'=> false === $cnt ); } //_____ public function convNameList ($ary) { $rst = array (); foreach ($ary as $key => $v) $rst[] = sprintf ('%1$s=:%1$s', $key); return implode (',', $rst); } } /* header ('Content-type: text/plain; charset=UTF-8'); header ('X-Content-Type-Options: nosniff'); $mysql = new MySQL(); $a = new TableRecorder ($mysql, "shain", "ID"); var_dump($a->select ('SELECT * FROM %%TABLE%% WHERE ?<%%ID%%', array (4))); */ ?>
順列を求める
Javascriptで順列を求める
考えたコード
function permutations (ary = [ ], r = ary.length) { function recursion (ary, r, A = []) { if (r == 0) return ary.map (a=> A.concat(a)); let result = []; for (let i = 0; i < ary.length; i++) { let aaa = [...ary], a = aaa.splice (i,1); result = result.concat (recursion (aaa, r-1, A.concat(a))); } return result; } return recursion (ary, r -1); }
短く1行で
let permutations=((f=(A,B=A.length,C=[])=>--B?A.reduce((a,b,c,[...d],_=d.splice(c,1))=>[...a,...f(d,B,[...C,b])],[]):A.map(a=>[...C,a]))=>f)(); console.log (permutation([0,1,2,3]));
- 再帰処理が必要なため、呼び出す関数をfにする
- [...d] は複写したものを使わないと元を破壊してしまう
- _=d.splice(c,1)) で配列から1つ削除するが、ここでは配列を返してしまうので使われない。その代わり同等の b を使う。
classで焼き直し(書きかけ)
class Permutation { constructor (ary = [ ], r = ary.length) { this.ary = ary; this.r = r; } get n () { return this.ary.length; } get length () { const fx = this.constructor.factorial; let {n, r} = this; return fx (n) / fx (n - r); } *generator (n = 0) { for (let i = 0, I = this.length; i < I; i++) { yield this.pattern (i); } } pattern (n) { if (n < 0 || this.length < n) throw new Error ('値が範囲外です'); /*書きかけ*/ return n; } patternAll () { return this.constructor.pattern (this.ary, this.r); } static factorial (n = 1) { let r = 1; for (let i = n; i > 1; r *= i--) ; return r; } static pattern (ary = [ ], r = ary.length) { function recursion (ary, r, A = []) { if (r == 0) { return ary.map (a=> A.concat(a)); } let result = []; for (let i = 0; i < ary.length; i++) { let aaa = [...ary], a = aaa.splice (i,1); result = result.concat (recursion (aaa, r-1, A.concat(a))); } return result; } return recursion (ary, r - 1); } }
パーリンノイズ
パーリンノイズ
- 参考URL
- https://mrl.cs.nyu.edu/~perlin/doc/oscar.html
- https://github.com/a-i-to/perlin-noise-sample
- GitHubから引用
-
function PerlinNoise(random) { if (random) { this._random = random; } else { this._random = Math.random; } this._gradient = {}; } PerlinNoise.prototype._randomGradient = function(x) { if (this._gradient[x] || this._gradient[x] === 0) { return this._gradient[x]; } var g = this._random() * 2 - 1; this._gradient[x] = g; return g; }; PerlinNoise.prototype.noise = function(x) { var x0 = Math.floor(x); var x1 = x0 + 1; var r0 = x - x0; var r1 = r0 - 1; var u = r0 * this._randomGradient(x0); var v = r1 * this._randomGradient(x1); var sx = r0 * r0 * (3 - 2 * r0); return 2 * (u + sx * (v - u)); }; this.PerlinNoise = PerlinNoise;
- 書き直したもの
-
class PerlinNoise { constructor (random = Math.random) { this.random = random; this.gradient = new Map; } randomGradient (x) { if (! this.gradient.has (x)) this.gradient.set (x, this.random () * 2 -1); return this.gradient.get (x); } noise (x) { let x0 = x |0, x1 = x0 + 1, r0 = x - x0, r1 = r0 - 1, u = r0 * this.randomGradient (x0), v = r1 * this.randomGradient (x1), sx = r0 * r0 * (3 - 2 * r0); return 2 * (u + sx * (v - u)); } }
- CANVAS に描画してみる
-
const PN = new PerlinNoise, canvas = CV0, ctx = canvas.getContext ('2d'), width = canvas.offsetWidth, height = canvas.offsetHeight / 2, centerY = height / 2, wave = 5, waveH = 100; canvas.width = width; ctx.beginPath (); ctx.moveTo (0, centerY); ctx.strokeStyle = 'rgba(255,0,0,.5)'; for (let px = 0; px < width; px += 1) { let py = centerY - PN.noise (px * wave / width) * waveH + waveH / 2; ctx.lineTo (px, py); } ctx.stroke ();
JavaScriptで数値を漢数字に変換する
俺様仕様。
使おうと思ったらまともに動かなかった!なんで?
ということで書き直した。
動かしているうちに短くなってしまった
もう少し煮詰めれば、さらに短くなりそうなのだけれど…
今日は終了!
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)&&i%4&&n==1?'':N[n])+M[i%4]+(i%4?r:K[(i/4)|0]+r)) return r; }) }
前に書いて動かなかったやつ
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; }) } [ "洋野町第123地割4567番地890123", 0, 10, 11, 12, 100, 111, 123, 1000, 1111, 1234, 10000, 11111, 12345, 100000, 111111, 123456, 1000000, 1111111, 1234567, 10000000, 11111111, 12345678, 100000000, 111111111, 123456789, 1000000000, 1111111111, 1234567890 ].forEach (n=>{ console.log (n, kansuji(n)); })
JavaScript class memo
JavaScript class memo
//ECMAScript2015: class class A { constructor (a, b) { Object.assign (this, {a, b}); this._val = null;//暗黙に内部変数 } get value () { return this._val; } set value (val) { this._val = val; } get clone () { let {a, b} = this; return new this.constructor (a, b); } static tool (...arg) { return new this (...arg); } static toolsFunc () { const func = { cbFunc: function (a) { return a+a} } return func; } static option (key = null) { const option = { }; return key ? option[key]: {...option}; } } class B extends A { //もし constructor が無い場合、以下が暗黙に実行される // constructor(...args) { super(...args); } constructor (a, b, c) { super (a, b);//先に実行すること this.c = c; } test () { let a = super.clone; } }