否応なく触れる機会が増すJavaScript
自分がJavaScriptを書くなどとは思ってもみなかった。
Html+CSS+JavaScriptは、今更言うまでもなくWebページ作成の為の重要な構成要素だ。
その中でもJavaScriptは、kintoneやらGoogleスプレッドシートやらの様々なクラウドサービスでExcelのVBAが如くその機能をユーザーがカスタマイズできるように利用されている。
クラウド全盛の昨今、JavaScriptの知識があればクラウドを身近に活用できるようになるだろう。
JavaScriptで2次元配列を作る
そんなことを感じていた折、いざJavaScriptで配列を操作しようとするとどうやっていいか分からない。しかし、今の世の中、ChatGPTという何でも相談できる心強い先生がいる。
単に配列を作るのではなく、空の2次元配列が必要となり、早速作り方を尋ねると以下の回答を得た。
let cells = Array(5).fill(null).map(() => Array(5).fill(null));
これは、5行5列の2次元配列を作らせた時の回答である。
ここで注目すべきは、map
関数だ。これは一体何をやっているのだろう?
分かりづらいことは、好きな言語で書き換えると理解が深まる。
以下はmap
とfill
の中身をC#で書いてみた。(書かせてみた)
public static class ArrayExtensions
{
public static TOutput[] Map<TInput, TOutput>(this TInput[] source, Func<TInput, TOutput> selector)
{
TOutput[] result = new TOutput[source.Length];
for (int i = 0; i < source.Length; i++)
{
result[i] = selector(source[i]);
}
return result;
}
public static T[] Fill<T>(this T[] source, T value)
{
for (int i = 0; i < source.Length; i++)
{
source[i] = value;
}
return source;
}
}
(参考まで『【C#】期せずして知識の詰まったメソッドを生んだ』)
ここで混乱するのは、Map
拡張メソッドの第2引数のFunc<TInput, TOutput> selector
だろう。
Map
の中ではselector
の実装が書かれていない。これはどういうことか?
selector
の実装はMap
メソッドを使用するユーザーが書く。Map
メソッド使用時に引数として実装を渡すのだ。ユーザーが元の配列を使って新たな配列に作り変えることができるが、どう作り変えるかをここでユーザー自身が実装する訳だ。だから第2引数はデリゲートのシグネチャのみで構わない。
これを使ってみる。
var cells = (new string[5]).Fill(null).Map(x => (new string[5]).Fill(null));
Console.WriteLine($"[\n {string.Join(",\n ", cells.Select(x => $" [{string.Join(", ", x.Select(y => y is null ? "null" : $"{y}"))}]"))}\n]");
JavaScriptのconsole.log
風に出力されるようにしてみた。
[
[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null]
]
配列の各要素に配列を格納しているので2次元配列となる。
気持ち悪いJavaScript
C#では実のところFill
メソッドは不要だ。これがJavaScriptだとどうか?
後ろのfill
を消してみた。
let cells = Array(5).fill(null).map(() => Array(5));
console.log(cells);
[
[ <5 empty items> ],
[ <5 empty items> ],
[ <5 empty items> ],
[ <5 empty items> ],
[ <5 empty items> ]
]
前のを消すと、、、
let cells = Array(5).map(() => Array(5).fill(null));
console.log(cells);
[ <5 empty items> ]
両方消すと、前のを消したのと同じ結果となった。
これが空配列か。JavaScript気持ち悪い、、、