LoginSignup
1
2

C#で、JavaScriptのmap関数っぽく2次元配列を作る

Last updated at Posted at 2023-05-31

否応なく触れる機会が増すJavaScript

自分がJavaScriptを書くなどとは思ってもみなかった。
Html+CSS+JavaScriptは、今更言うまでもなくWebページ作成の為の重要な構成要素だ。
その中でもJavaScriptは、kintoneやらGoogleスプレッドシートやらの様々なクラウドサービスでExcelのVBAが如くその機能をユーザーがカスタマイズできるように利用されている。
クラウド全盛の昨今、JavaScriptの知識があればクラウドを身近に活用できるようになるだろう。

JavaScriptで2次元配列を作る

そんなことを感じていた折、いざJavaScriptで配列を操作しようとするとどうやっていいか分からない。しかし、今の世の中、ChatGPTという何でも相談できる心強い先生がいる。
単に配列を作るのではなく、空の2次元配列が必要となり、早速作り方を尋ねると以下の回答を得た。

JS
let cells = Array(5).fill(null).map(() => Array(5).fill(null));

これは、5行5列の2次元配列を作らせた時の回答である。
ここで注目すべきは、map関数だ。これは一体何をやっているのだろう?
分かりづらいことは、好きな言語で書き換えると理解が深まる。
以下はmapfillの中身をC#で書いてみた。(書かせてみた:sweat_smile:

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;
    }
}

(参考まで:point_right:『【C#】期せずして知識の詰まったメソッドを生んだ』

ここで混乱するのは、Map拡張メソッドの第2引数のFunc<TInput, TOutput> selector だろう。

Mapの中ではselectorの実装が書かれていない。これはどういうことか?

selectorの実装はMapメソッドを使用するユーザーが書く。Mapメソッド使用時に引数として実装を渡すのだ。ユーザーが元の配列を使って新たな配列に作り変えることができるが、どう作り変えるかをここでユーザー自身が実装する訳だ。だから第2引数はデリゲートのシグネチャのみで構わない。

これを使ってみる。

C#

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を消してみた。

JS
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> ]
]

前のを消すと、、、

JS
let cells = Array(5).map(() => Array(5).fill(null));
console.log(cells);
出力
[ <5 empty items> ]

両方消すと、前のを消したのと同じ結果となった。

これが空配列か。JavaScript気持ち悪い、、、:confounded:

1
2
2

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
1
2