yucatio@システムエンジニア

趣味で作ったものいろいろ

JavaScriptでPython風のzip関数を実装する

JavaScriptzip関数がなかったので実装してみました。以下のように、各配列の同じインデックスの要素をまとめます。

const a1 = [1, 2, 3]
const a2 = ["Jan", "Feb", "Mar"]
const a3 = ["Garnet", "Amethyst", "Aquamarine"]

zip(a1, a2, a3)
#=> [[1, "Jan""Garnet"], [2, "Feb""Amethyst"],  [3, "Mar""Aquamarine"]]

各配列の長さが異なる場合には、一番短い配列の長さに切り詰められます。

const a1 = [1, 2, 3, 4]
const a2 = ["Jan", "Feb", "Mar", "Apr", "May"]
const a3 = ["Garnet", "Amethyst", "Aquamarine"]

zip(a1, a2, a3)
#=> [[1, "Jan""Garnet"], [2, "Feb""Amethyst"],  [3, "Mar""Aquamarine"]]

zip関数

zip関数の実装です。

const zip = (...arrays) => {
  const length = Math.min(...(arrays.map(arr => arr.length)))
  return new Array(length).fill().map((_, i) => arrays.map(arr => arr[i]))
}

コードの解説

まず、関数の定義の部分を解説します。レスト構文を使用して、引数全てをarraysに格納します。

const zip = (...arrays) => {

}

例えば、

const a1 = [1, 2, 3, 4]
const a2 = ["Jan", "Feb", "Mar", "Apr", "May"]
const a3 = ["Garnet", "Amethyst", "Aquamarine"]

zip(a1, a2, a3)

と呼び出したとき、arrays

[
  [1, 2, 3, 4],
  ["Jan", "Feb", "Mar", "Apr", "May"],
  ["Garnet", "Amethyst", "Aquamarine"]
]

です。以下、引数にこの配列を渡したときの動作を説明します。

次に、各配列の長さを求めます。

const zip = (...arrays) => {
  arrays.map(arr => arr.length)
  #=> [4, 5, 3]
}

この中の最小値は、Math.minとスプレッド演算子を使用して、以下のように書けます。

const zip = (...arrays) => {
  const length = Math.min(...(arrays.map(arr => arr.length)))
  #=> const length = Math.min(...[4, 5, 3])
  #=> const length = Math.min(4, 5, 3)
  #=> const length = 3
}

3回繰り返すので、new Array(length).fill().map((_, i) => i)の構文を使用します。

const zip = (...arrays) => {
  const length = Math.min(...(arrays.map(arr => arr.length)))
  new Array(length).fill().map((_, i) => i))
  #=> [0, 1, 2]
}

fillをはさむ理由については、こちらの記事をご覧ください。

yucatio.hatenablog.com

各配列のi番目の要素は、

arrays.map(arr => arr[i])

で取得することができます。よくわからない場合は、iではなく、0、1、2など具体的な数字で考えるとよいです。例えば、各配列の0番目の要素は、

arrays.map(arr => arr[0])
#=> [1, "Jan""Garnet"]

です。

これをmapに渡す関数の戻り値にします。

const zip = (...arrays) => {
  const length = Math.min(...(arrays.map(arr => arr.length)))
  return new Array(length).fill().map((_, i) => arrays.map(arr => arr[i]))
  #=> [[1, "Jan""Garnet"], [2, "Feb""Amethyst"],  [3, "Mar""Aquamarine"]]
}

以上でzip関数の完成です。

zip_longest

Pythonzip_longestにあたる関数はMath.minの部分をMath.maxにするだけです。 こちらの記事に詳しい動作を載せています。

yucatio.hatenablog.com

イテレータの使用

Pythonではイテレータを使用して配列の要素にアクセスしています。list[i]のようにインデックスを指定してアクセスするよりも、イテレータの方が速いことが期待されるからでしょう。 (参考: 組み込み関数 — Python 3.8.1 ドキュメント )

JavaScriptにもイテレータがあるので そちらを利用しようかと思いましたが、あまり慣れている書き方ではないので今回は見送りました。 ( 参考:Array.prototype.values() - JavaScript | MDN)

rubyのzipメソッド

rubyにもzipメソッドがあり、似た動きをするのですが、こちらはArrayクラスのインスタンスメソッドです。こちらはレシーバの要素数が作成後の配列の長さになります。

Array#zip (Ruby 2.7.0 リファレンスマニュアル)

[1,2,3].zip([4,5,6], [7,8,9])
# => [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

プログラミングで初学者のときにつまづいたこと

プログラミングでつまづいてきたことというブログ記事を見たので、私も書いてみます。

satoru-takeuchi.hatenablog.com

mizchi.hatenablog.com

自己紹介

記事をリンクしたお2人と違って大したプログラマではないですが、システムエンジニアとして働いて10年経ってみて今の仕事が向いていると思っているところです。

大学でC言語Javaを習って、仕事はWeb系で主にJavaを使用しています。

以下、つまづいたことです。だいたい古いのから新しいものになっています。

代入文

a = 1
b = 2
c = a + b

でcが3になるのは分かったのだが、

a = a + 1

これを見て、"左右が等しくない。"と混乱し、そこで思考が止まってしまった。 半年後くらいに代入文という言葉を覚え、上記は"a + 1を計算した結果をaに入れる"だということが分かった (が慣れるまでにはもう少しかかった)。

アルゴリズム

プログラムそれ自体よりもアルゴリズムでつまづく(大学の授業で習った。言語はC言語。)

バブルソートわからない。わかってもコードに落とし込めない。2重ループが難しすぎる。

こんなに便利な世の中なのに、並び替えをするのにいちいち自前でプログラミングをしなければいけないなんて、どうなっているのだと思った。 (色々と認識が間違っていた)

Java

オブジェクト、インスタンス、クラス

用語の説明を何度読んでも理解ができない。他にもとにかく馴染みのないカタカナ語が多すぎて嫌になった。

あるとき、C言語の構造体に関数を足したのがクラスだと気づきそこから理解が進んだ。が、C言語を習っていなかったらと思うと震える。

Javaオブジェクト指向 (継承、ポリモーフィズムカプセル化)

惑星クラスを拡張したのが、水星クラス、金星クラス、土星クラスとか、 犬クラスだったら"ワン"と鳴いて、猫クラスだったら"ミャー"と鳴くとか、何に使うかがわからなかった。 値の隠蔽(カプセル化)が重要という割に、setterで値を操作できているではないか、と思った。

理解できるようになったのは、Javaデザインパターンを読んでから。


ちなみに"オブジェクト指向とは何か"はこちらの記事でWindows95を開発した中島聡さんの言葉を引用しています。

yucatio.hatenablog.com

インターフェース

インターフェースも何に使うか長年の疑問だった。実装がないとは何の役にも立たないのではないか。

確かこの本だったと思うけど、"例えば、自動販売機、外側に見える部分がちゃんと仕様通りに動いていれば、中に人が入っていて、手でジュースを出してもよい。自動販売機の、外から見える部分がインターフェース、中の機械とかが実装"、といったことがイラスト付きで書いてあって、その図がシュールで印象に残った。この例からなんとなく理解し始めたように思う。


その後、"仕様と実装を分けて考える"ということができるようになってきたのでインターフェースの使い所もはっきりしてきた。

Rubyのmap関数

array.map {|i| i * 2 }

で、なぜ各配列の値が2倍されるのか分からなかった。Javaしかほぼやってこなかったので、変換後の配列が定義されていないことが不思議だった。

JavaのMapとRubyのmapは全くの別物ということに思い当たったのと(JavaのMapはRubyのhash)、 とりあえずJavaでの記法(for文を使うもの)と対比させて覚えた。

プログラミング以外でのつまづきも多い

リンク先での記事でも「オブジェクト」「スタック」「ヒープ」が多義語で分かりにくかったとの記載があったが、 自分の場合は「ドメイン」「インスタンス」が多義語で混乱した。がこれはプログラミングではないもの(プログラミングの周辺知識ではあるが)も含まれているので機会があれば書きたい。

最近はプログラミング言語それ自体というより、周辺のツールで使用される概念や用語の理解に苦労する。 最近だとDockerの用語の理解でつまづいた。

あとがき

書きながら、プログラム始めたばかりのころ 全然コードが動かなくて吐きそうになったのを思い出しました。

とりあえず私から言えることは、Javaは最初に学ぶような言語ではないということです。

eclipseのJavadocの警告設定の各設定値の意味【後編】

Javadocの記述が不完全なときに警告を出そうとして、どのような設定があるか調べたメモです。

チーム開発でJavadocをどの程度書くかどうか、意識を統一するのにこの記事をご活用いただければと思います。

前編の記事

yucatio.hatenablog.com

未指定の Javadoc タグ

"未指定の Javadoc タグ"をONにすると、メソッドに定義されていてJavadocに記載されていないパラメータや例外などがある場合に警告を出します。

f:id:yucatio:20200113175535p:plain

メンバーの可視性を次のように設定

設定した可視性以上のJavadocのみ、"未指定の Javadoc タグ"の警告を出します。

オーバーライドしたメソッドの実装を無視

Javaでは、オーバーライドしたメソッドのJavadocは、子クラスの内容で親クラスの内容を上書きした内容となります。 以下の例では、子クラスでdescriptionと変数xの記述を上書きし、他のparamとreturnについては、親クラスの記述が引き継がれています。

f:id:yucatio:20200113180300p:plain

"オーバーライドしたメソッドの実装を無視"をOFFにすると、オーバーライドしたメソッドであっても、未指定の Javadoc タグがある場合には警告を出します。

f:id:yucatio:20200113180008p:plain

ただし、@Overrideアノテーションが付いている場合、警告は出ません。

f:id:yucatio:20200113180021p:plain

詳しい仕様と仕様が策定された経緯につきましてはこちらをご覧ください。

6.15 complains about missing @return tag in a overridden method · Issue #2869 · checkstyle/checkstyle · GitHub

メソッド型パラメータを無視

メソッド型パラメータとは、 ジェネリックメソッドにおいて、メソッドの戻り値の型の直前に書かれた<T>などの型の仮型パラメータのことです。 (参考: Java ジェネリクス(クラス、メソッドを定義する) - Qiita )

"メソッド型パラメータを無視"がONのときは、この<T>のためのJavadoc(@param <T>)がなくても警告を出しません。

OFFにすると、警告を出します↓

f:id:yucatio:20200113195747p:plain

未指定の Javadoc コメント

"未指定の Javadoc コメント"をONにすると、Javadocが記載されていない場合に警告を出します。

"メンバーの可視性を次のように設定"を"Protected"にした時の表示です↓

f:id:yucatio:20200113215408p:plain

メンバーの可視性を次のように設定

設定した可視性以上のJavadocのみ、警告を出します。

オーバーライドしたメソッドの実装を無視

"オーバーライドしたメソッドの実装を無視"をONにすると、オーバーライドしたメソッドにJavadocが無くても警告を出しません。

オーバーライドしたメソッドは、Javaでは親クラスのJavadocが使用されるため、指定しなくても問題ないことが多いかもしれません。

"オーバーライドしたメソッドの実装を無視"をOFFにすると、オーバーライドしたメソッドにも警告を出します。

f:id:yucatio:20200113220027p:plain

"未指定の Javadoc タグ > オーバーライドしたメソッドの実装を無視" の設定とは違い、こちらは@Overrideアノテーションのあるなしでの挙動の違いはありません。

オーバーライドしたメソッドに親と同じ内容のJavadocを書ときは、{@inheritDoc}タグを使うと便利です。

  /**
   * {@inheritDoc}
   */
  @Override
  public int calcA(int x, int y, int z) {
    return x + y + z + 1;
  }

参考: オーバーライドしたメソッドのJavadoc - 気付いたとき、気が向いたとき。by ykhr

環境

あとがき

"未指定の Javadoc タグ > オーバーライドしたメソッドの実装を無視" の設定が自分の想定と違った動作をしたので意外と苦戦しました。

参考サイト

eclipseのJavadocの警告設定の各設定値の意味【前編】

Javadocの記述が不完全なときに警告を出そうとして、どのような設定があるか調べたメモです。

チーム開発で、Javadocをどの程度書くかどうか、意識を統一するのにこの記事をご活用いただければと思います。

Javadocの警告設定

Javadocの書き方がよくないときに警告を出す設定の場所は、 設定 > Java > コンパイラー > Javadoc です。

f:id:yucatio:20200112222657p:plain

Javadocコメントを処理

"Javadocコメントを処理"をONにすると、Javadocとメソッドが連携されます。 変数名を選択したときにJavadocのparamの変数名もハイライトされます。

ONのとき↓

f:id:yucatio:20200112223145p:plain

OFFのとき↓

f:id:yucatio:20200112223156p:plain

また、ONにすると、変数のリネーム時にJavadocのparamの変数も同時に変更されます。

ONのとき↓

f:id:yucatio:20200112223411p:plain

OFFのとき↓

f:id:yucatio:20200112223421p:plain

誤った形式の Javadoc コメント

"誤った形式の Javadoc コメント"をONにすると、波かっこが閉じていないときなどに警告を出します。

f:id:yucatio:20200112223630p:plain

メンバーの可視性を次のように設定

設定した可視性以上のJavadocのみ、警告を出します。

可視性をProtectedにしたときに、PublicとProtedtedメソッドのにのみ警告が出て、パッケージとPrivateのメソッドに警告は出ません↓(タグ引数の検証をONにしたときの警告)

f:id:yucatio:20200112224059p:plain

"タグ引数の検証"をONにすると、@param, @throws, @exceptions, @see, @linkに 指定されたクラスやメソッドが存在しないときに警告を出します。

min1という引数はメソッドに存在しないため、警告が出ます↓

f:id:yucatio:20200113142031p:plain

f:id:yucatio:20200113141532p:plain

Nowhere.nomthodという存在しないクラスとメソッドを参照しているので警告が出ます↓

f:id:yucatio:20200112224211p:plain

不可視参照をレポート

"不可視参照をレポート"をONにすると、 不可視なメソッドなどを参照をしたときに警告を出します。不可視な参照とは、例えば他のクラスのprivateなメソッドや定数です。

他のクラス(SamplePrivateクラス)のprivateな定数(DEFAULT_NAME)を参照しているので、警告が出ます↓

f:id:yucatio:20200112224444p:plain

使用すべきでない参照をレポート

"使用すべきでない参照をレポート"をONにすると、非推奨(Deprecated)となったメソッドや変数を参照したときに警告します。

f:id:yucatio:20200112224653p:plain

タグ記述の欠落

"タグ記述の欠落"の設定では、 @param 変数名@returnなどのタグのあとの記述が無いときに警告を出します。

@return タグの検証ではその名の通り、@returnタグの後に何も書かれていなければ警告を出します。その他のタグの後には何も書かれていなくても警告を出しません。

f:id:yucatio:20200112225611p:plain

全ての標準タグを検証にすると、全ての標準タグにおいて、タグの記述がない場合に警告を出します。標準タグとは javadoc - Java API ドキュメントジェネレータ に記載されているタグです。

f:id:yucatio:20200112225624p:plain

後編

長くなったので続きます。

yucatio.hatenablog.com

環境

参考サイト

eclipseの警告表示の重大度レベルごとの挙動

前回の記事で、eclipseの警告レベルをどれにするか迷ったので、各重大度レベルでの挙動を確認しました。

yucatio.hatenablog.com

eclipseの警告表示の設定

eclipseを使用していると、黄色の波線と警告マーク(3角形の中に!)が表示されたことがあるでしょう。 これらの設定は、 設定 > Java > コンパイラー > エラー/警告 で変更可能です。

f:id:yucatio:20200110081256p:plain

エラー、警告、情報、無視の違い

エラー/警告の設定では、eclipseが問題を検出したときにの重大度を設定できます。

重大度レベルごとのeclipseの挙動です。

重大度レベル 表示
エラー 問題がある箇所に赤の点線が引かれ、該当する行及びファイル名にバツ(×)印がつきます。さらに、プログラムの実行時に"必要なプロジェクトでのエラー"のダイアログが表示されます。("続行"を押すと実行できます。)
警告 問題がある箇所に黄色の点線が引かれ、該当する行及びファイル名にエクスクラメーションマーク(!)がつきます。実行時にダイアログは出ません。
情報 問題がある箇所に青の波線が引かれ、該当する行及びファイル名に"i"マークがつきます。実行時にダイアログは出ません。
無視 何も表示しません。

エラー

エラーの時の表示です。

f:id:yucatio:20200110081144p:plain

実行時にダイアログが表示されます↓

f:id:yucatio:20200110081158p:plain

警告

警告の時の表示です。

f:id:yucatio:20200110081127p:plain

情報

情報の時の表示です。

f:id:yucatio:20200110081113p:plain

無視

無視の時は何も表示されません。

f:id:yucatio:20200110081101p:plain

エラー、警告、情報の一覧を表示する

現在のワークスペースの警告の一覧を表示するには、ウィンドウ > ビューの表示 > その他 > 一般 > マーカーを開きます。

f:id:yucatio:20200110081050p:plain

"マーカー"のビューに現在のワークスペース内に存在するエラーや警告が表示されます。各項目をクリックすると該当箇所へジャンプすることができます。

f:id:yucatio:20200110081025p:plain

以上、eclipseの警告設定と各重大度レベルごとの挙動でした。

環境

うっかりミスを防ぐeclipseおすすめ設定6つ【後編】

前編に引き続き、うっかりミスを防止(警告)するeclipseの設定をまとめました。

前編の記事

yucatio.hatenablog.com

セミコロン2つを検知

行末のセミコロンを間違って2つ打ってしまうのもありがちなミスです。

設定 > Java > コンパイラー > エラー/警告 > 潜在的なプログラミングの問題 > 空のステートメントの警告レベルを、"情報"にします。

f:id:yucatio:20200107115743p:plain

設定前↓

f:id:yucatio:20200107121016p:plain

設定後↓

f:id:yucatio:20200107121029p:plain

マウスオーバーするとセミコロンの除去がサジェストされます↓

f:id:yucatio:20200107121040p:plain

何も記述されていないブロックを検出

何も記述されていないブロックを検出する方法です。 何も書かれないブロックが必要な場合もあります。そんなときはコメントを書いておくか消しててほしいものです。

設定 > Java > コンパイラー > エラー/警告 > コード・スタイル > 何も記述のない空のブロックの警告レベルを、"警告"にします。

f:id:yucatio:20200107130435p:plain

設定前↓

f:id:yucatio:20200107130540p:plain

設定後↓

f:id:yucatio:20200107130459p:plain

空ブロックにコードかコメントを書くように促されます↓

f:id:yucatio:20200107130553p:plain

@Overrideのつけ忘れを防ぐ

オーバーライドしたメソッドに@Overrideアノテーションが付いていない場合に警告します。

設定 > Java > コンパイラー > エラー/警告 > 注釈 > '@Override' 注釈の欠落の警告レベルを、"警告"にします。

f:id:yucatio:20200107195325p:plain

設定前↓

f:id:yucatio:20200107195355p:plain

設定後↓

f:id:yucatio:20200107195413p:plain

@Overrideをつけるようにとの警告が表示されるようになりました↓

f:id:yucatio:20200107195433p:plain

環境

あとがき

以上、うっかりミスを防ぐためのおすすめeclipse設定でした。書きながら、とりあえず 設定 > Java > コンパイラー > エラー/警告の"無視"となっているところを全て"情報"以上にすればよいのではと思うのでした。

うっかりミスを防ぐeclipseおすすめ設定6つ【前編】

こんにちは。プログラミングでうっかりミスをしてしまうブログ主です。特にスペルミスがひどいです。 レビューで指摘されると申し訳無い気持ちになるので、そのようなうっかりミスを防止(警告)するeclipseの設定をまとめました。

空白の表示

空白タブ、全角空白、改行文字などを表示するオプションです。

設定 > 一般 > エディター > テキスト・エディター > 空白文字を表示にチェックを入れます。

f:id:yucatio:20200107085812p:plain

次に、可視性の構成をクリックして全てチェックを入れます。

f:id:yucatio:20200107085824p:plain

設定前↓

f:id:yucatio:20200107085900p:plain

設定後↓

f:id:yucatio:20200107085911p:plain

タブは^、スペースは.、全角スペースはで表示されました。改行コードは、LF(Unixの改行コード)は、CRLF(Windowsの改行コード)はで表示されます。

チーム開発時にONにしてほしいオプションナンバー1です。空白とタブを混ぜると後々見にくさの原因になります。

スペルチェック

スペルをチェックをするオプションです。

設定 > 一般 > エディター > テキスト・エディター > スペル > スペル・チェックを使用可能にするにチェックを入れます。

f:id:yucatio:20200107091023p:plain

設定前↓

f:id:yucatio:20200107091117p:plain

設定後↓

f:id:yucatio:20200107091131p:plain

赤の波線が出ている箇所にマウスオーバーすると、修正の候補が表示されます↓

f:id:yucatio:20200107091144p:plain

Javadocのチェック

Javadoc@paramなどの項目がメソッドの定義と一致しているかをチェックするオプションです。リファクタリングのときにJavadocを修正し忘れることはよくあるので入れておきたい設定です。

設定 > Java > コンパイラー > Javadocを開き、以下のような設定にします。

f:id:yucatio:20200107113825p:plain

各設定項目の挙動についてはこちらの記事をご覧ください。

yucatio.hatenablog.com

yucatio.hatenablog.com

設定前↓

f:id:yucatio:20200107113839p:plain

設定後↓

f:id:yucatio:20200107113905p:plain

メソッドで宣言されていないパラメータがJavadocにあると警告を出します↓

f:id:yucatio:20200107113920p:plain

returnに何も記述されていないと警告を出します↓

f:id:yucatio:20200107113931p:plain

存在しないクラスやメソッドを参照すると警告を出します↓

f:id:yucatio:20200107113942p:plain

メソッド宣言にあって、Javadocに無いパラメータがあるときに警告を出します↓

f:id:yucatio:20200107113954p:plain

環境

後編に続く

長くなったので続きます。

yucatio.hatenablog.com