このページについて
このページは、paiza ラーニング内に開設されているコンテンツ「レベルアップ問題集」で取り扱われているプログラミング課題について、独自の見解を述べたものです。
見解については、paizaラーニングの規約に基づき、許可されている範囲でのみ公開していますが、その内容については paiza とは一切関係なく、また paiza の立場を反映したものではありませんのでご注意ください。
挑戦する課題
レベルアップ問題集の文字列処理メニューから「部分文字列 (paizaランク D 相当)」を取り上げます。
以下は、問題公開 Web ページからの引用です。
問題
文字列 S と整数 i , j が与えられるので、 S の i 文字目から j 文字目までの部分文字列を出力してください。
入力される値
1 2 |
S i j |
期待する出力
S の i 文字目から j 文字目までの部分文字列を 1 行で出力してください。
考え方
Swift の場合、文字列(
String)の添字に
Int 型は使えないため、
String.Index 型で添字を与える必要がある。
このような場合、
index(_:offsetBy:) を使って目的の添字を得る。
このメソッドに与える引数の一つ目は基準となるインデックスとなるが、 String 型は startIndex というプロパティで文字列の最初のインデックスを得ることができるため、基準の値としてこの値を渡し、 offsetBy に先頭からの場所を与えることで、目的とする添字に対応する String.Index を得る。
文字列の添字を範囲演算子を使って指定すると、指定した範囲の文字列を得ることが可能である。
解答例
1 2 3 4 5 6 7 8 9 10 11 12 |
// 切り取る文字列 let s = readLine()! // 切り取る範囲 let ia = readLine()!.split(separator: " ").map { Int($0)! } // 切り取り開始、切り取り終了のインデックスを得る let i = s.index(s.startIndex, offsetBy: ia[0] - 1) let j = s.index(s.startIndex, offsetBy: ia[1] - 1) // スライスとして表示 print(s[i...j]) |
どれほど効率的になるか疑問だが、 String.Index の計算まで一気にやってしまう方法もある。
1 2 3 4 5 6 7 8 |
// 切り取る文字列 let s = readLine()! // 切り取る範囲 let ia = readLine()!.split(separator: " ").map { Int($0)! }.map{ s.index(s.startIndex, offsetBy: $0 - 1) } // スライスとして表示 print(s[ia[0]...ia[1]]) |
あるいは、入力文字列を「文字の配列」にして、指定した範囲だけ出力。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 切り取る文字列を「文字の配列」にする let s = readLine()!.map { String($0) } // 切り取る範囲。あらかじめ -1 しておく let ia = readLine()!.split(separator: " ").map { Int($0)! - 1} // 指定した範囲だけ逐次出力 for i in ia[0]...ia[1] { // 改行しないよう、terminator を空文字 "" にする print(s[i], terminator: "") } // 最後の改行 print() |