@ledsun blog

無味の味は佳境に入らざればすなわち知れず

C#とJavaScriptとRubyのコレクション操作

大抵のプログラミング言語でコレクション(列挙できる何か)をメソッドチェーンで操作できます。 プログラミング言語ごとに、ちょっとずつちがうので整理してみようと思います。 僕の馴染みのあるC#JavaScriptRubyでそれぞれ書いてみます。

お題

お題は「入力された数値の配列からヌルを取り除き10倍して、3で割ったあまりで分類する」です。 実用的な例だとは思っていません。

C#

C#ではEnumerable クラス (System.Linq) | Microsoft Docs を使います。

var source = new int?[] { 1, null, 2, 3, null, 4 };

var emptyHash = new Dictionary<int, List<int>> {
  { 0, new List<int>() },
  { 1, new List<int>() },
  { 2, new List<int>() }
};
var result = source.OfType<int>()
                   .Select(x => x * 10)
                   .Aggregate(emptyHash, (acc, e) =>
                   {
                       acc[e % 3].Add(e);
                       return acc;
                   });

foreach (var (key, value) in result)
{
    Console.WriteLine($"{key}: {String.Join(",", value)}");
}
  • 結果を保持するためのDictionaryの初期化
  • ヌル許容型からヌル非許容型への変換
  • 結果の出力

が面倒でした。 型付けが強いプログラミング言語は、こういう練習用の短いプログラミングを書くにはまだるっこしいです。 C#はリハビリ中です。 もっと簡単な書き方があるかもしれません。

JavaScript

JavaScriptではArray - JavaScript | MDNを使います。

const source = [1, null, 2, 3, null, 4];

const result = source
  .filter((e) => e)
  .map((e) => e * 10)
  .reduce(
    (acc, e) => {
      acc[e % 3].push(e);
      return acc;
    },
    { 0: [], 1: [], 2: [] }
  );

console.log(result);

僕が、もっとも慣れているプログラミング言語です。 シュッと書けました。

Ruby

Rubyではmodule Enumerable (Ruby 3.1 リファレンスマニュアル)を使います。

source = [1, nil, 2, 3, nil, 4]

result = source
  .find_all { _1 }
  .collect { _1 * 10 }
  .inject({ 0 => [], 1 => [], 2 => [] }) do
    _1[_2 % 3] << _2
    _1
  end

p result

Rubyは同じ関数にいろいろな名前がついていて面白いです。

参考

追記

JavaScriptfilter((e) => e)だと0もはじいちゃいますね。 filter((e) => e !== null)の方が良いです。