JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptで文字列内の各単語の先頭文字を大文字にする3つの方法

エンジニアらしい思考力を養うのに役立つ、初心者向けのコーディング課題は数多くあります。そのひとつが「与えられた文字列の中にあるすべての単語の先頭文字を大文字にする」という課題です。この記事では、まず問題の内容を確認し、その上でJavaScriptによる複数の解法を紹介します。

問題の概要

関数capitalizeは引数strを受け取ります。strに含まれるすべての単語の先頭文字を大文字にした文字列を返してください。その際、入力がない場合や誤った型の入力が渡された場合といったエッジケースも考慮してみましょう。

取り組み方(アプローチ)

  1. まず問題文をもう一度読み込み、キーワードを見つけてメモしたり強調表示したりしましょう。
  2. 問題の意味を整理します。コーディング課題で最も難しいのは「何を求められているのか」を正確に把握する部分です。問題をしっかり理解できれば、解決までの道のりはぐっと近くなります。
  3. 疑似コードで解法のアイデアを書き出します。実際に実行できるコードである必要はなく、日本語の文章でも十分です。
与えられたものを理解する:
	関数が与えられている
	何らかの入力を受け取る

返すべきものを理解する:
	文字列

最初にすべきことは何か?
入力が文字列だと分かっているとき、どんな選択肢があるか?
利用できる文字列メソッドはあるか?
メソッドを知らない場合はどうやって調べるか?
入力が空文字列だったり、数値やオブジェクトだったらどうするか?
まずはforループで文字列を走査するところから始めてみよう。
	その次はどうする? …という具合に続ける…

問題を一歩ずつ丁寧に分解すると、不正な入力や空文字列が渡される可能性といったエッジケースに気づきやすくなり、問題を論理的なステップへ落とし込む方法も見えてきます。これはいわば実験の段階であり、正解・不正解はありません。あるのは「どうアプローチするか」という思考だけです。その思考が的外れになることもありますが、それこそが「うまくいかないアプローチ」を学ぶ貴重な経験になります。

筆者の経験では、問題を声に出して説明できるレベルまで分解すると、ロジックが頭に入りやすくなりました。人によって相性はあるかもしれませんが、あなたにも合うならぜひ試してみてください。この程度の規模の問題にいちいち疑似コードを書くのは大げさに感じるかもしれません。しかし、今のうちに習慣化しておけば、はるかに難しい問題に直面したときに大きな武器になります。

解決策

解決策1:split()+forループ+replace()/charAt()

<!DOCTYPE html>
<html>
 <head>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width">
   <title>for loop</title>
 </head>
 <body>
   <div id="root"></div>
  <script async defer>
    let capitalize = (str) => {
      let arr = str.split(' ');
      for(let i = 0; i < arr.length; i++ ) {
         arr[i] = arr[i].replace(arr[i].charAt(0),  arr[i].charAt(0).toUpperCase());
     }
     return arr.join(' ');
   }
   let root = document.getElementById('root');
   root.innerHTML = JSON.stringify(capitalize('the quick brown fox jumped over the lazy dog'));
  </script>
 </body>
</html>

最初の解法では、文字列をスペースで分割(split)します。これにより、各単語が個別の要素となった配列が得られます。配列をforループで回すことで、各単語の文字にアクセスできます。そして、インデックスiの要素(arr[i])を、その0番目の文字(arr[i].charAt(0))を大文字に置き換えた結果で再代入します。最後にjoin(' ')で配列をスペース区切りの文字列に結合して返します。

解決策2:split()+map()+slice()

<!DOCTYPE html>
<html>
 <head>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width">
   <title>Map</title>
 </head>
 <body>
   <div id="root"></div>
  <script async defer>
    let capitalize = (str) => {
      // スペースで分割して、扱う対象を明確にする
      let arr = str.split(' ') // 2つの引用符の間に必ず半角スペースを入れること
      // mapメソッドを使用
      arr.map((word, index, array) => {
        array[index] = array[index][0].toUpperCase() + array[index].slice(1);
        return array[index];
      })
      console.log(arr)
      return arr.join(' ');
    }
   let root = document.getElementById('root');
   root.innerHTML = JSON.stringify(capitalize('the quick brown fox jumped over the lazy dog'));
   </script>
 </body>
</html>

この解法も冒頭はほぼ同じですが、ループ処理にES6の配列メソッドmap()を使っている点が異なります。コールバック内では、1文字目にtoUpperCase()を適用し、残りの部分はslice(1)で切り出し、両者を文字列連結して新しい単語を作っています。処理後の配列をjoin(' ')で結合して返します。

解決策3:正規表現

<!DOCTYPE html>
<html>
 <head>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width">
   <title>repl.it</title>
 </head>
 <body>
   <div id="root"></div>
  <script async defer>
    let capitalize = (str) => {
      let regex = /(^|\s)\S/g
       return str.replace(regex, letter => letter.toUpperCase());
    }
   let root = document.getElementById('root');
   root.innerHTML = JSON.stringify(capitalize('the quick brown fox jumped over the lazy dog'));
   </script>
 </body>
</html>

この解法では、正規表現/(^|\s)\S/gを使って、「文字列の先頭(^)または空白文字(\s)の直後に位置する非空白文字(\S)」をすべて検索します。末尾のgフラグはグローバル検索を意味し、パターンに一致するすべての箇所が対象になります。あとはreplace()メソッドで、マッチした文字を大文字に変換する関数に置き換えるだけです。

まとめ

ここで紹介した解法が唯一の正解というわけではありません。こうした課題を重ねるうちに、記事やブログで紹介されているものとは違う、あなた自身の解法が生まれることもあるでしょう。それはとても良いことです。「エンジニアのように考えられるようになってきた」証拠だからです。それこそが、この種の課題に取り組む最大の目的です。

ちなみに、ある調査ではブートキャンプ受講者の81%が「受講後、テック業界でのキャリアの見通しに自信を持てるようになった」と回答しています。また、受講開始から初めての仕事獲得までの平均期間は6ヶ月未満でした。キャリアチェンジを検討しているなら、ブートキャンプとのマッチングサービスを活用してみるのもひとつの手です。

諦めずに続けることが大切です。ところで、今回紹介した解法はどれもエッジケースを処理していません。引数が空文字列だった場合、あるいは数値だった場合はどうすればよいでしょうか? 上記のコードに、そうしたケースへの対応を追加してみてください。

ヒント:否定演算子(!)を使えば、strが存在するかどうかを条件分岐で判定できます。また、MDNのドキュメントを参照して、型が不明な値の型を判別するメソッドを探してみましょう。

もうひとつの課題:まだであれば、「JavaScriptで文字列を逆順にする」コードチャレンジにも挑戦してみてください!

さらに学びたい人へのおすすめリソース

Rubyでの正規表現の使い方 – Ruby向けの記事ですが、正規表現自体は多くの言語で共通の概念です。解決策3で登場するRegExp構文の理解を深めるのに役立ちます。

JavaScript Replace Text:ステップバイステップガイド – replace()メソッドに特化したチュートリアルです。解決策1で使用されているメソッドの詳細を学べます。

  1. C#の正規表現を使って文字列内の各単語の最初の文字を抽出・表示する方法

    C#では、正規表現(Regex)を活用することで、文字列から特定のパターンに一致する部分を簡単に抽出できます。この記事では、文字列内の各単語の最初の文字を取り出して表示する方法を解説します。対象となる文字列例として、次のような文字列を扱います。string str = The Shape of Water got an Oscar Award!;使用する正規表現パターン各単語の最初の文字を表示するには、次の正規表現を使用します。@\b[a-zA-Z]このパターンの構成要素は以下の通りです。\b:単語の境界(ワードバウンダリ)を表します。単語の先頭位置にマッチします。[a-zA-Z]:英字1文字

  2. Pythonで各単語の先頭文字を大文字に変換するプログラム

    英語の小文字だけで構成された文が与えられたとき、各単語の最初の文字だけを大文字に変換する方法を解説します。 たとえば、入力が s = i love my country の場合、出力は I Love My Country となります。 解決の手順 この問題は、以下のステップで解くことができます。 文字列 s を空白で分割し、単語のリストを作成する 結果を格納するための空のリストを用意する 各単語に対して capitalize() 関数を使って先頭文字を大文字化し、リストに追加する リスト内のすべての単語を空白区切りで連結して返す 実装例 実際のコードを見てみましょう。 def solv