最初からn文字が一致する行を削除するプログラム(修正と考察)

タイトルの通り最初からn文字が一致する行を削除するプログラムを作りました。

こちらにアクセスしてください。
http://marumaru.tonkotsu.jp/wp-content/themes/MaruMaru2/NChara.html

使い方

UIがアレなんでわかりにくいですが(時間があれば改善します)、使い方を簡単に説明します。

まず、上のテキストエリアに重複行を削除したいものをぶち込みます。
一番上のインプット欄は「最初の何文字が一致していたら削除するか」を決めます。
一行まるまる一致には対応していません(時間があれば作ってみます。)

「変換」をクリックすると、重複行を削除したものが、左(もしくは上)に、重複したものが右(もしくは下)のテキストエリアに出力されます。

 

 

考察

以下は開発にあたって結構悩んで、人に聞いた上で解決したので、どこに問題があったのか、また新たに知ることができたアルゴリズムについて考察してみたいと思います。

僕が書いたヘボコード。

言うまでもないが、言語はjavascript。ライブラリにjQueryを使用している。
変換ボタンを押すと、開業するごとに配列にぶち込んでいる。つまり1行が1つの要素の配列を作成。
最初のfor文で先程作った配列lineの行先頭n文字をlineFirstCharsという配列に入れていく。

次のfor文で重複検証をしている。最初のlineの要素数分ループさせる。内側のforではkをj+1から始めることで、必ず発生する重複を避けている。
恐らく問題が合ったのは次。spliceでlineから重複行を取り除いているのだが、このとき取り除かれたところはそれ以降の要素によって詰められるので、line.lengthが変わったり、forループが適用されない箇所が出てきたりしている。

もちろん、消えた要素のところを詰めない方法であるdeleteもあって、一度全部詰めずに削除した後に、要素の抜けている部分を一気に削除してしまう方法も試してみたが、上手く行かなかった。
$.grepで配列の空を削除 – フロント炒飯
とまぁ、ミスってるコードの考察なんてどうでもいいので、ちゃんと動くコードの考察に入る。

 

 

ご教示いただいた神コード

始めのところはあまり変わりはない。
重要なのはさきほど「問題なのは」と書いたfor文である。
ああ、そういえばjavascriptでの変数の宣言の仕方が「var」以外に「let」と「const」があることを知ったのもこのコードを見たときである。
詳しくは書かないが、letとconstを用いるとブロックスコープが有効になる。再代入がある場合はletでそれ以外はconstで賄える。

ミソは内側のfor文がkのデクリメントでループされているところだろうか。
重複があればループを抜け、次に進むことで、重複行がいくつあっても確実に重複したものとしていないものとを分別することができている。

このアイディアは斬新だなと感じた。

コメントを残す