ワンライナーで行こう!(JavaScriptで配列操作いろいろ)
ワンライナーで行こう!(JavaScriptで配列操作いろいろ):
はてなキーワードによると、
※ネタが思い付き次第順次追加していきたいと思います。「もっと短くできる!」「イクナイ」等のご指摘や、他のワンライナーネタがありましたら、コメント欄にお願いします。
start=1, end=10の配列(公差1の等差数列)を生成
before = 10 から after = 1 へ置換
target = 9 を削除
昇順の場合は(a,b)=>a-b。破壊的メソッドのため、=演算子での上書き不要。
Array.prototype.reverse()そのまま。破壊的メソッドのため、=演算子での上書き不要。
map(e => +e)で数値形式の文字列から数値に変換するのがミソ。
filter(e => e.length===3)で、要素数が3に満たない配列[7,8]を落としている
上で作成した2つのベクトル v=[[ 1, 2, 3 ], [ 4, 5, 6 ] ]を使う
内積と同様、v=[[ 1, 2, 3 ], [ 4, 5, 6 ] ]を使う
N=3の場合をN=2にしただけ
だいぶ苦しくなってきた。ツーライナーに見えるのは気のせいです…
ブランチのペアは上記の m= [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ]を使用。ここでは任意のハッシュ関数をhash()としています。
マークルツリーアルゴリズムについての解説はこちらを参照しました。
本来、ブランチは文字列で、ループの前に1度ハッシュ関数を通す等の前処理が必要ですが、とりあえず主要部分のみ。
hash()を単なる2要素の足し算にして検算した結果↓(実際に使う場合はSHA256等のハッシュ関数に置き換える)
ワンライナーとは
はてなキーワードによると、「ワンライナー」とは、たった1行だけのプログラムです。PerlやRubyを使うと、1行だけでもかなりの仕事ができます。 プログラムを書きたいが、エディタを起動するほどの手間はかけたくない、というときに威力を発揮します。達人ともなると、ちょっとした文字置換や計算をするワンライナーを、即興で作って使い捨てることもあります。PerlやRubyは、ワンライナーを書くために役立つオプションを豊富に持っています。Javascriptでも、ES2015以降、アロー演算子や、Array.prototype.filterやArray.prototype.map等の関数でワンライナーが作りやすくなりました。配列操作系を中心に、便利なワンライナー集を作ってみました!
※ネタが思い付き次第順次追加していきたいと思います。「もっと短くできる!」「イクナイ」等のご指摘や、他のワンライナーネタがありましたら、コメント欄にお願いします。
startからendまでの連続した数値配列を生成する
start=1, end=10の配列(公差1の等差数列)を生成var array = Array.apply(0,new Array(end-start+1)).map((e,i) => start+i); //console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
特定の値の要素を入れ替える
before = 10 から after = 1 へ置換 array = array.map(e => e===before ? after : e); //console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 1 ]
特定の値の要素を削除する
target = 9 を削除array = array.filter(e => e!==target); //console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8, 1 ]
配列を降順に並び替える
昇順の場合は(a,b)=>a-b。破壊的メソッドのため、=演算子での上書き不要。array.sort((a,b)=>b-a); //console.log(array)--> [ 8, 7, 6, 5, 4, 3, 2, 1, 1 ]
配列を逆順に並び替える
Array.prototype.reverse()そのまま。破壊的メソッドのため、=演算子での上書き不要。array.reverse(); //console.log(array) --> [ 1, 1, 2, 3, 4, 5, 6, 7, 8 ]
配列から重複する値を削除する
array = array.filter((e,i,s) => i===s.indexOf(e)); //console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8 ]
2つの配列を結合する
array = array.concat(array); //または array = [...array,...array]; // console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 ]
配列から重複する値のみ残す
array = array.filter((e,i,s) => s.indexOf(e)!==s.lastIndexOf(e)); // console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 ]
配列から重複する値のみ残した後、重複削除
array = array.filter((e,i,s) => i!==s.indexOf(e)); // console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8 ]
配列の中身を結合した文字列を作る
var string = array.join().replace(/,/g,""); // console.log(string) --> 12345678
数値文字列を分割して数値配列にする
map(e => +e)で数値形式の文字列から数値に変換するのがミソ。array = string.split('').map(e => +e); //または array = Array.from(string).map(e => +e); // console.log(array) --> [ 1, 2, 3, 4, 5, 6, 7, 8 ]
配列中の数値の合計値を得る
var sum = array.reduce((a,b) => a+b); // console.log(sum) --> 36
配列中の数値の最大値を得る
var max = array.reduce((a,b) => a<b ? b : a); // console.log(max) --> 8
隣り合うN個の要素をまとめた配列の配列を作る(N=3)
filter(e => e.length===3)で、要素数が3に満たない配列[7,8]を落としているvar v = array.map((e,i,s) => i%3===0 ? s.slice(i,i+3) : null).filter(e => e!==null && e.length===3); // console.log(v) --> [[ 1, 2, 3 ], [ 4, 5, 6 ] ]
3次元ベクトルの内積
上で作成した2つのベクトル v=[[ 1, 2, 3 ], [ 4, 5, 6 ] ]を使うvar ip = v[0].map((e,i) => v[0][i]*v[1][i]).reduce((a,b) => a+b); // console.log(ip) --> 32
3次元ベクトルの外積
内積と同様、v=[[ 1, 2, 3 ], [ 4, 5, 6 ] ]を使うvar op = v[0].map((e,i) => v[0][(i+1)%3]*v[1][(i+2)%3]-v[0][(i+2)%3]*v[1][(i+1)%3]); // console.log(op) --> [ -3, 6, -3 ]
隣り合う2要素をまとめた配列の配列を作る(N=2)
N=3の場合をN=2にしただけvar m = array.map((e,i,s) => i%2===0 ? s.slice(i,i+2) : null).filter(e => e!==null && e.length===2); // console.log(m) --> [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ]
マークル木演算
だいぶ苦しくなってきた。ツーライナーに見えるのは気のせいです…ブランチのペアは上記の m= [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ]を使用。ここでは任意のハッシュ関数をhash()としています。
var i=~~Math.pow(m.length,1/2);while(i>0){m=m.map((e,i,s)=>i%2===0?[hash(e),hash(s[i+1])]:null).filter(e=>e!==null); i=+(i-1);}
本来、ブランチは文字列で、ループの前に1度ハッシュ関数を通す等の前処理が必要ですが、とりあえず主要部分のみ。
hash()を単なる2要素の足し算にして検算した結果↓(実際に使う場合はSHA256等のハッシュ関数に置き換える)
const hash = (a) => a[0]+a[1]; // console.log(...m) --> [ 10, 26 ] //スプレッド演算子で2重括弧状態を解除
コメント
コメントを投稿