Swiftのコーディングテストのすゝめ

# はじめに
本記事は[STECH / 愛知工業大学 システム工学研究会 共同企画 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/stech-ait-advent)の4日目の記事です．

タイトル通りコーディングテストはSwiftでやろう！という布教記事です．(競プロはやったことないのでそっちには触れません)

私は現在Androidエンジニアを目指してなんやかんやしている大学生ですが，Paizaのスキルチェックや選考のコーディングテストなどは全てSwiftを使っています．
Swiftの良いところを本記事でバチこりと紹介して，皆さんも使うようになってくれたら嬉しいです．

# 実行速度の速さ
Swift(日本語で迅速)という名の通り，Swiftは処理速度がかなり早いです．
[公式のSwiftページ](https://www.apple.com/jp/swift/)によるとPython2.7の最大8.4倍，Objective-Cの最大2.7倍高速に動作するようです．はやそう(小並感)．
コードは正しいのにRunTimeErrorで０点になると激萎えしますよね．実際それでKotlinからSwiftに鞍替えした民です．(KotlinのおかげでPaizaのレーティングが200下がった)  

# コーディングのしやすさ
Swiftは個人的にかなり使いやすい言語だと感じています．
文末のセミコロンがいらなかったり，型推論がついていて変数宣言に型がいらなかったりと細かいポイントで使用者に優しいです．
また，コードの記述方法も一般的なオブジェクト指向型言語と大きく離れていないので，JavaやJavaScriptなどを触ったことがあれば，かなり手に馴染むかなと思います．
特にJavaScriptと結構似ているなと個人的には感じています．

# 便利な配列,文字列操作
Swiftは2014年に登場した比較的モダンな言語です．
モダンな言語なだけあってやはり便利な関数が多く用意されています．
特に，コーディングテストによく使用する配列や文字列操作系は豊富でソートや絞り込み，単体処理などが楽にできるので紹介していきます．

### sort,sorted
まずは定番の並べ替えです．
基本的な使い方は次のようになります．

```Swift:sortの使い方
配列.sort{ 並べ替え条件 }     // 呼び出し元自体をソート後に変更
配列.sorted{ 並べ替え条件 }   // 戻り値がソート済み配列

// 例
var a = [4,2,7,3]          // 配列の宣言
var b = a.sorted{$0 < $1}  // 昇順ソート
a.sort{$0 > $1}            // 降順ソート

print(a)                   // [7,4,3,2]
print(b)                   // [2,3,4,7]
```
どちらも{}に要素を入れ替える条件式を代入することでソートすることができます．
条件式に使われている$0や$1とはなんぞやというと，配列内の要素を示します．$0が当該要素で$1がその一つ後ろの要素という意味ですね.$2,$3と数字を増やすことでより後ろの要素を指定することもできます．
sortとsortedの違いですが，関数の呼び出し元配列を並べ替えるか否かです．sortを呼び出すと今回の場合は配列aの中身そのものが並べ替えられてしまいます.varではなくletで宣言した変数にsortを使うとSwiftくんにバチギレられるので気をつけましょう．一方で，sortedを呼び出すと配列aを並べ替えた結果の配列を戻り値として返します．配列aの中身を変えることなくソート済みの配列を用意することができます．
用途によって使い分けましょう．

### filter
次に紹介するのは，絞り込みを行うfiletr関数です，
基本的な使い方は次のようになります．

```Swift:filterの使い方
配列.filter{ 絞り込み条件 }

// 例
var a = [4,2,7,3]          // 配列の宣言
a = a.filter{ $0 < 4 }     // 4未満の数字で絞り込み

print(a)                   // [2,3]
```
基本的な使い方は前述したsortedと同じです.{}内に，記述した条件式が真となる要素を絞りこんだ配列を返してくれます．
Bool型を返す関数を絞り込み条件に使うことで，複雑な条件や自作クラス要素でも簡単に絞り込みができます．
また,filter関数は実は配列だけではなく文字列でも用意されています．具体的なコードは後述しますが,数字や特定文字の抽出などが可能です．

### map
最後に紹介するのは，配列の各要素に処理を施せるmap関数です．
言葉だけだと分かりにくいので実際のコードを見てみましょう.

```Swift:mapの使い方
配列.map{ 処理 }

// 例
var a = [4,2,7,3]          // 配列の宣言
a = a.map{ $0*10 }         // 全要素の値を１０倍

print(a)                   // [40,20,70,30]
```
mapもsortやfilterと似たような感じで{}内に行いたい処理を記述します．
処理の戻り値がそのまま配列の要素に置き換えられるので関数などを呼び出して複雑な処理を行うこともできます．

# 楽々拡張関数
拡張関数とはなんぞやという人もいると思うのでまずは拡張関数について説明します．
拡張関数とは，既に定義されたクラスなどに関数を追加できる機能のことです．Int型やString型に自前の関数を後付けで追加ができます．
拡張関数は以下のように使います．

```Swift:拡張関数の使い方
extension クラス名 {
     追加したい関数
 }

// 例
let a = "hogehuga"
a.printOut()               // hogehuga
 
extension String {
    func printOut() -> Void{
        print(self)
    }
}
```
これでStirng型にprintを行う関数，printOut関数を追加することができました．
Kotlinだともうちょっと複雑な書き方になるので簡潔に書けるのはとても良きです．
関数を単独で用意して使用するのと変わらんくね？と思う人もいるかもしれませんがそんなことはありません．ちゃんと拡張関数にもメリットがあります．

それが，簡潔に記述や呼び出しができる点です．
拡張関数を使うことで一般的な関数宣言よりも構造的に簡潔に表現することができるようになります．
拡張関数では，クラス内で関数が定義されているため，メンバ変数などを引数に取ることなく使用することができます．不要な引数が減らせるということですね．
また，関数の結果を関数の引数に使いたい場合があると思います．一般的な関数の場合，入れ子な構造になって可読性が下がってしまうと思いますが，拡張関数で宣言した場合は，ピリオドで連結することができるので可読性を保ちながら実装ができます．(可読性が上がったり上がらなかったりもする)

ただ，型それ自体に強く依存しない処理や動作を行う場合は普通に関数宣言をして使った方が可読性や拡張性が高くなる場合が多いので，しっかりと使い分けましょう．

# コーディングテストによく使うパターン
それでは，これまでコーディングテストなどでよく使った実際のコードとその説明をしていきます．

#### Int型配列で標準入力
```Swift:Int型配列で標準入力
var a = readLine()!.split(separator: " ").map { Int(String($0))! } 
```
まず，readLine()によって標準入力から一行読み込みます．それを，splitによってseratorの値で文字列を区切って配列にし，mapを使ってString型からInt型に変換します．

#### 文字列から数字のみを抽出して
```Swift:文字列から数字のみを抽出
let text = "hoge8940"
var a = text.filter{ "0123456789".contains($0) }  // "8940"
var b = text.filter( "0123456789".contains )      // "8940"
```
前述したようにfilter関数はStringでも用意されているため，正規表現のような使い方ができます．
containsは引数にした値が呼び出し元文字列に含まれている場合はtrueを，含まれていなければfalseを返すあらかじめ用意されている関数です．
変数のaとbは同じ処理を行なっています．bはaを短縮した書き方です．

#### 文字列から正規表現でマッチした部分を削除する
```Swift:文字列から正規表現でマッチした部分を削除
import Foundation

var a = "hoge8940"
a = a.deleteNumber()                   // hoge

extension String {
    func deleteNumber() -> String {
        return replacingOccurrences(   // self. が省略されている
            of: "[0-9]",               //正規表現で数字を指定
            with: "",
            options: .regularExpression)
    }
}
```
replacingOccurrencesはStringにあらかじめ用意されている関数です．本来ならば「文字列.replacingOccurrences」と呼び出す必要があるのですが,拡張関数の呼び出し元に対して使用する場合は省略した呼び出しが可能です．
また,replacingOccurrencesはofと一致した文字列をwithの値に置換するという関数なので削除だけではなく好きな文字列への置換なども可能です．

# おわりに
以上でSwiftの布教活動は終わりになります．
この記事でみなさんがSwiftに対して興味を持ってもらえたら幸いです．
変数や関数の宣言，細かい言語仕様といった基本的な部分は説明しなかったので，「Swiftを使ってみたい！」と感じたなら色々調べてみて実際に触ってみてください．その時にnil結合や三項演算子,enumといった言葉についても調べるとSwiftの魅力がより感じられるかもしれません．
ただ，Swiftの主な使い道がAppleデバイス向けのアプリ開発ぐらいしかないという~~致命的な~~弱点はネックなポイントですね．