LoginSignup
17
9

More than 5 years have passed since last update.

ワンライナーで行こう!(JavaScriptで配列操作いろいろ)

Last updated at Posted at 2018-12-02

ワンライナーとは

はてなキーワードによると、

「ワンライナー」とは、たった1行だけのプログラムです。PerlやRubyを使うと、1行だけでもかなりの仕事ができます。 プログラムを書きたいが、エディタを起動するほどの手間はかけたくない、というときに威力を発揮します。達人ともなると、ちょっとした文字置換や計算をするワンライナーを、即興で作って使い捨てることもあります。PerlやRubyは、ワンライナーを書くために役立つオプションを豊富に持っています。

Javascriptでも、ES2015以降、アロー演算子や、Array.prototype.filterやArray.prototype.map等の関数でワンライナーが作りやすくなりました。配列操作系を中心に、便利なワンライナー集を作ってみました!

※ネタが思い付き次第順次追加していきたいと思います。「もっと短くできる!」「イクナイ」等のご指摘や、他のワンライナーネタがありましたら、コメント欄にお願いします。

startからendまでの連続した数値配列を生成する

start=1, end=10の配列(公差1の等差数列)を生成

var array = Array(end-start+1).fill().map((e,i) => start+i);
//または
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);
//または
var max = Math.max.apply(null, array);
//または
var max = Math.max(...array);
// 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重括弧状態を解除
17
9
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
17
9