LoginSignup
0

More than 5 years have passed since last update.

[checkio]The most wanted letter

Last updated at Posted at 2017-06-17

エンジニアを目指すプログラミング初心者が、しこしことcheckioを使って勉強をしていきます。
感銘を受けた他のエンジニア様のコードを分析します。

今回の問題は入力として受け取った文字列の中でもっとも出現頻度の高いcharacterを返すというもの。
複数の文字列がもっとも高い出現頻度を持つ場合はアルファベット順で若い方を返す。
だが空白文字や記号、テメーはだめだという鬼畜仕様。

まず自分のコード

function mostWanted(data) {
    data = data.replace(/\s+|!|\d+|-|,/g, "").toLowerCase();
    var text = [];
    var mostCha = [];
    var mostCount = 1;
    var count = 1;
    for (let i of data) {
        text.push(i);
    };
    text.sort(function(a,b) {
        if (a<b) return -1;
        if (a>b) return 1;
        else return 0;
    });
    for (let i = 0; i < text.length; i++ ) {
        if(text[i] == text[i+1]) {
            count += 1;
            if (count > mostCount) {
                mostCount = count;
            }
        } else {
            count = 1;
        }
    };
    for (let i = 0; i < text.length; i++ ) {
        if(text[i] == text[i+1]) {
            count += 1;
            if (count == mostCount) {
                mostCha.push(text[i]);
            }
        } else {
            count = 1;
        }
    };
    if (mostCount == 1) {
        mostCha.push(text[0]);
    }
    return mostCha[0];
}

うむ美しい(錯乱)
すごい無駄しかない気がすることはわかるのだが、どうすることもできなかった。

次に本題のすげーなと思ったコード。

function mostWanted(data) {
    s = data.toLowerCase().split("").sort()
    max = 0
    for(c of "abcdefghijklmnopqrstuvwxyz".split("")){
        n = s.indexOf(c) >= 0 ? s.lastIndexOf(c) - s.indexOf(c) + 1 : 0
        if(n > max){
            max = n
            maxc = c
        }
    }
    return maxc
}

なんでこんな短くなるの・・・

分析

まず一行目では
・ 文字列を小文字に変換し(.toLowerCase)
・ 空白文字を取り除き(テキストを引数で区切った配列を生成)(.split(""))
・ 並び替えをしている(.sort())

んーsort()は文字列にも使えるのか・・・?
最初にそれでできるのではないかと思って試して見たら、"--- is not a function"のエラーが出てきて、調べて見たらarray classのmethodらしいことがわかり、自分の解答では配列を使うようにしたんだけど・・・
そのうちわかったら追記しよう。

アッー
split()で配列にしてました。なるほど。

2行目はmaxという変数を定義。

3-7行目のfor文では・・・
3...一つ一つアルファベットを要素として持つ配列を作りつつ、それを一つずつループする動作
4...nという変数の中で
・ cがs配列の中にあるかを確認
・ 存在していれば、s配列の最後(lastIndexOf)から最初(indexOf)をindexとして引いて個数を求める。
・存在していなければ0をnに代入
5...今の文字列がmaxより大きければ・・・
6...maxにnを代入
7...maxcにcを代入してこの文字列が一番多いですよ
でmaxcを最後にリターンして完了。美しい(確信)

反省

まずすでにアルファベット順にしているため、最大数の文字をストックしておく配列は特に必要なかった。
出てくるforループを2つにしたのも、特に必要なかった。
あと、文字列だけを見るために、自分のではわざわざreplaceで取り除いているので、これではいちいちダメなものがでるたびに追加しなきゃいけない。その点後者のコードは必要なものだけを配列として定義して比較しているので、スマート。
もっと簡潔にかけるよう頑張ろう。

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
0