JavaScript の console.log で菱型を書く
いつの間にか食レポじゃなくなっていた『俺の食べログ』さんで面白そうな問題があったので。
function diamond(length) { const height = 2 * length - 1; const width = height; const halfline = (width + 1) / 2; const space = ' '; const ast = '*'; for (var i=1; i <= height; i++) { var numOfAst = 0; var spaces = ''; var asts = ''; if (i <= halfline) { numOfAst = i*2-1; } else { numOfAst = width - 2 * (i - halfline); } spaces = space.repeat( (width - numOfAst) / 2); asts = ast.repeat(numOfAst); console.log(spaces + asts + spaces); } } diamond(10); /* * *** ***** ******* ********* *********** ************* *************** ***************** ******************* ***************** *************** ************* *********** ********* ******* ***** *** * */
PHPで1行FizzBuzz
array_map(function($e){$arr=["FizzBuzz","Fizz","Buzz", $e];echo $arr[ceil(($e%3)/2) + 2 * ceil(($e%5)/4)];}, range(1, 100));
適当な関数があれば変数宣言も省けそうなのだが。
Quick sort, Merge sort and Heap sort in PHP
<?php /** * QUICK SORT */ function quick_sort($a){ if(sizeof($a) <= 1){ return $a; } $left_a = []; $right_a = []; $pivot = array_pop($a); foreach($a as $e){ if($e <= $pivot){ array_push($left_a, $e); }else{ array_push($right_a, $e); } } $left_a = quick_sort($left_a); $right_a = quick_sort($right_a); return array_merge($left_a, [$pivot], $right_a); } /** * MERGE SORT */ function merge_sort($a){ $left_a = []; $right_a = []; if(sizeof($a) <= 1){ return $a; } $middle = (int)sizeof($a)/2; $left_a = array_slice($a, 0, $middle); $right_a = array_slice($a, $middle); $left_a = merge_sort($left_a); $right_a= merge_sort($right_a); return merge($left_a, $right_a); } function merge($left, $right){ $result = []; while(sizeof($left) > 0 && sizeof($right) > 0){ $l = $left[0]; $r = $right[0]; if($l <= $r){ array_push($result, array_shift($left)); }else{ array_push($result, array_shift($right)); } } while(sizeof($left) > 0){ array_push($result, array_shift($left)); } while(sizeof($right) > 0){ array_push($result, array_shift($right)); } return $result; } /** * HEAP SORT */ function heap_sort($a){ $result = $a; // create heap for($i=0;$i<sizeof($a);$i++){ $result = upheap($result, $i); } for($i=sizeof($a)-1;$i>0;$i--){ // put the first element into sorted list area $result = swap($result, 0, $i); $result = downheap($result, $i); } return $result; } function swap($arr, $a, $b){ $temp = $arr[$a]; $arr[$a] = $arr[$b]; $arr[$b] = $temp; return $arr; } // make arr[0] - arr[$n] heap function upheap($arr, $n){ while($n > 0){ // get parent value $m = (int)(($n+1)/2-1); if($arr[$m] < $arr[$n]){ // if a child is bigger than its parent, swap them $arr = swap($arr, $m, $n); }else{ // if $arr is valiable heap, break break; } // check parent's value $n = $m; } return $arr; } // make arr[0] - arr[$n-1] heap function downheap($arr, $n){ $parent_to_swap = 0; $child_to_swap = 0; while(true){ $l_child = (int)($parent_to_swap+1)*2-1; $r_child = (int)($parent_to_swap+1)*2; // if left child overflow the target, break if($l_child >= $n){ break; } // Is left child bigger than its parent? if($arr[$l_child] > $arr[$child_to_swap]){ $child_to_swap = $l_child; } // Is right child within target and bigger than its parent? if($r_child < $n && $arr[$r_child] > $arr[$child_to_swap]){ $child_to_swap = $r_child; } // no need to swap, break if($child_to_swap === $parent_to_swap){ break; } $arr = swap($arr, $child_to_swap, $parent_to_swap); // continue checking with the swaped child as a new parent $parent_to_swap = $child_to_swap; } return $arr; } $arr = [5,3,2,9,7,0,1,4,6,8]; var_dump(quick_sort($arr)); echo "<br/>"; var_dump(merge_sort($arr)); echo "<br/>"; var_dump(heap_sort($arr)); ?>
PHPUnit の setUp関数と setUpBeforeClass 関数の違い
PHPUnit の setUp 関数について勘違いしていた。
setUp 関数は、クラス内のテストケースそれぞれについて、開始前に1回ずつ起動する。インスタンスのプロパティの初期化に用いるとよい。
一方、setUpBeforeClass 関数は、クラスをインスタンス化する前に1度だけ起動する。DBへの接続や、テストケースで共通に使う値(ユーザなど)の作成に用いると良い。これは static 関数なので、当然 static な変数しか扱えないことに注意。
tearDown 関数と tearDownAfterClass 関数にも同様の関係が言える。
setUp 関数は全部のテストケース実行前になされるものだと思っていたら違ったのでメモメモ。
CSS の text-decoration 要素の設定値
設定値は6つあり、主な設定値は、overline、underline、line-through の3つ。
<span style='text-decoration: overline'>overline</span>
出力: overline
いつつかうんだ?これ。
<span style='text-decoration: underline'>underline</span>
出力: underline
<span style='text-decoration: line-through'>line-through</span>
出力: line-through
あとは
- none
- initial
- inherit
の3つを設定できる。
ポートフォリオサイト的なの作った
1日でやっつけた割にはそこそこのできになったと思います。英文チェック全然やってないから添削必要だとは思うけど。
ぼくはデザインスキルほぼ皆無なので、こういった素敵ツールは役に立ちます。
なおサムネイルにホバーすると浮き上がった感じに見えるエフェクトは
さんを パk オマージュさせていただきました。この場を借りて感謝申し上げます m(_ _)m
Object.create()時にenumerableをtrueにしておかないとオブジェクトがクローンできない件
Object.create()とは
JavaScriptにおいて、プロトタイプベースの継承を行う際によく用いられる関数です。
拙著過去記事も参照ください
JavaScriptにクラスはありません - オブジェクトリテラルとコンストラクタパターン編 -
JavaScriptにクラスはありません - プロトタイプで継承編 -
オブジェクト指向でよくみられる、「親クラスのプロパティをすべて再利用しつつ、子クラス独自のプロパティも定義する」ことをJavaScriptで実現できます。使用例を次に示します。
var obj = function obj(){}; obj.prototype.prop = function(){alert('prop')}; // オブジェクト生成 var object = Object.create(obj.prototype,{ hoge: {value: 'fuga'}, foo: {value: 'bar'} }); var subobj = function subobj(){}; subobj.prototype = new obj(); // objのプロパティを継承 subobj.prototype.myprop = function(){alert('myprop')}; // 独自のプロパティ
例に示したように、Object.createの引数はふたつあります。第1引数は新しいオブジェクトのプロトタイプ、そして第2引数はプロパティオブジェクトと呼ばれる、オブジェクトのプロパティを要素に持つオブジェクトです。 このプロパティオブジェクト、設定値がいろいろあるのですが、悪いこと言わないのでenumerableをtrueにしておけという話です。
enumerableをtrueにしておかないと
何が困るかというと、underscore.jsやlodash.jsを使ってオブジェクトをクローンする時に困るのです。 JavaScriptにおいて、オブジェクトや配列の代入は参照渡しです。そのため、あるオブジェクトを変数に格納して、そののちオブジェクトを編集すると、変数の中身も変わります。
var obj = {hoge: 'fuga'}; var a = obj; obj.hoge = 'piyo'; console.log(a.hoge); // 'piyo'
残念ながら通常のJavaScriptで実体の代入を実現するのは非常にめんどくさいです。そのためライブラリを用いるのが一般的です。わたしはlodash.jsで用意されている_.cloneDeep()関数をよく使っています。
var obj = {hoge: 'fuga'}; var a = _.cloneDeep(obj); //実体のコピーを作成して代入 obj.hoge = 'piyo'; console.log(a.hoge); // 'fuga'
ところが、Object.create()で作られたオブジェクトをこの関数に適用させる場合、プロパティのenumerableがtrueになっていないとコピーされないのです。 enumerableはデフォルトでfalseになっているので(なぜだ……)、明示的にtrueを指定してやる必要があります。
var obj = function obj(){}; obj.prototype.prop = function(){alert('prop')}; // オブジェクト生成 // ダメな例 var no_good_object = Object.create(obj.prototype,{ hoge: {value: 'fuga'}, foo: {value: 'bar'} }); // これはOK var good_object = Object.create(obj.prototype,{ hoge: {value: 'fuga', enumerable: true}, foo: {value: 'bar', enumerable: true} }); var a = _.cloneDeep(no_good_object); // これはクローンされない! var b = _.cloneDeep(good_object); // これはクローンされる
この現象に直面して、lodash.jsのバグじゃないかと思いライブラリのコードを追いかけて数時間無駄にしたのが今日の筆者です。ということで、enumerableをtrueにして快適JavaScriptライフをすごしましょう!