String in Swift(日本語)


## はじめに
[公式ドキュメント](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html)

公式ドキュメントのうち、ほぼ同じ内容の部分を排除して、ざっくりと日本語訳した。具体例とかは削りぎみ（最後の方直訳っぽくなってしなったので修正したい）
内容の抜け落ちは殆ど無いはず
ざっくり全部日本語で読みたい人用

Swift 2.2の資料を元に書いています

間違い、修正すべき点など遠慮無くコメントでお願いします


## String and Characters
CharacterのCollectionとしてなど、様々な方法でアクセスできる

## String Literal
""でくくったのがStringのリテラル

```swift
var emptyString = ""               // empty string literal
var anotherEmptyString = String()  // initializer syntax
```

これらは同じ

```swift
emptyString.isEmpty()
```

で空文字かどうか判断できる

## String Mutability
varなら変更可能、letなら変更不可
letなのに変更しようとすると、コンパイル時にエラーがでる

## Strings Are Value Types
Stringは[Value Type](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-ID88) = 値渡し
自分が変更しないなら、変更されてないことが保証される

## Working with Characters
`.characters`プロパティを呼び出すと、一文字ずつCharacter型のオブジェクトとして取り出せる

```swift
for character in "Dog!🐶".characters {
    print(character)
}
```

> D
o
g
!
🐶

`for-in`ループについては[こちら](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html#//apple_ref/doc/uid/TP40014097-CH9-ID121)

もしくは独立に、一文字のStringリテラルからも、Character型の変数/定数を作れる

```swift
let exclamationMark: Character = "!"
```

CharacterのArrayをStringのイニシャライザに渡すと、合体したStringを作れる

```swift
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
```

> Cat!🐱

## Concatenating Strings and Characters
文字列の結合。Stringはoperator (+) で新しいStringが作られる（そしてこれを代入すれば更新できる）

```swift
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcomeは"hello there"と等しくなる
```

operator (+=) でも同様に動く

CharacterをStringに追加するには、String型のappend()メソッドを使う

```swift
let exclamationMark: Character = "!"
var welcome = "hello there".append(exclamationMark)
// welcome now equals "hello there!"
```


ただし、Characterは一文字しか保持できないので、Characterに対して文字やCharacterを追加することは出来ない

Momo:
StringのArrayは`.joinWithSeparator()`メソッドで結合できる

## String Interpolation
String interpolationとは、定数・変数・リテラル・式の値をStringリテラルの中にいれて、新しいStringをつくること

```swift
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
```

"\\(multiplier)"というプレースホルダが、実際の値に置き換えられる

ちなみに、()内には、エスケープされていないバックスラッシュ、改行コードは入れられないが、その他はいられる

## Unicode

Unicodeは国際的な、エンコーディングの標準
Swiftにおける、StringやCharacterは、完全にUnicodeに準拠している。(本節参照)

### Unicode Scalars
SwiftでのString型は、裏では、UnicodeScalar値から作られている
UnicodeScalar値は、文字や記号に対応する、

- U+0061 は LATIN SMALL LETTER A ("a")
- U+1F425 は FRONT-FACING BABY CHICK ("🐥")

といった21ビットのユニークな数字

ただし、Unicodeスカラー値は全て文字に割り当てるわけではなく、未来のための予約語もある。また、割り当てられてる文字には、上で示した、 LATIN SMALL LETTER AやFRONT-FACING BABY CHICKといった名前もあることも多い


### Special Characters in String Literals
Stringリテラルの中にも特殊文字を入れられる（本節参照）

- エスケープされた特殊文字

| エスケープ | 表示 |
|:-----------:|:------------:|
|\0|null character|
| \\\\ |backslash|
| \t |horizontal tab|
| \n |line feed|
| \r |carriage return|
| \\" |double quote|
| \' |single quote|


- "\u{n}"


"\u{n}"として、nは、1–8桁の16進数にすると、任意のユニコード文字を入れられる（Unicodeのコードポイントが存在するもののみ）


以下、特殊文字の例
wiseWords定数は２つのダブルコーテーションを含む。
その他のdollarSign, blackHeart, sparklingHeartはユニコードスカラー値フォーマットの例

```swift
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
let dollarSign = "\u{24}"        // $,  Unicode scalar U+0024
let blackHeart = "\u{2665}"      // ♥,  Unicode scalar U+2665
let sparklingHeart = "\u{1F496}" // 💖, Unicode scalar U+1F496
```

### Extended Grapheme Clusters
SwiftのCharacter型のインスタンスは、全て1つのextended grapheme clusterを示す。1つのextended grapheme clusterは、1つの人間が読める文字を表す
（Unicodeスカラー値は1つまたは複数合わさってextended grapheme clusterを構成する）

※ grapheme cluster = 書記素クラスタ

例：
"é"は、
ユニコードスカラー値é (LATIN SMALL LETTER E WITH ACUTE, or U+00E9) 
でも表せるが
e (LATIN SMALL LETTER E, or U+0065) + COMBINING ACUTE ACCENT scalar (U+0301)
という組み合わせでも表現できる

COMBINING ACUTE ACCENT scalarは前の文字に適用されて、Unicode対応のテキストレンダリングシステムによって描画される時に、e + COMBINING ACUTE ACCENTはéに変わる

```swift
let eAcute: Character = "\u{E9}"                         // é
let combinedEAcute: Character = "\u{65}\u{301}"          // e followed by ́
// eAcute is é, combinedEAcute is é
```

Extended grapheme clustersによって、とても柔軟に、多くの複雑な文字を、一つのCharacter型の値として表せる
ハングルの音節は、precomposedとdecomposed sequenceのどちらでも表せるが、Swiftではどちらも、1つのCharacter型の値としてみなされる。

```swift
let precomposed: Character = "\u{D55C}"                  // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}"   // ᄒ, ᅡ, ᆫ
// precomposed is 한, decomposed is 한
```

Extended grapheme clustersのおかげで、囲いマークで他のUnicode文字を囲って、一つのCharacter型の値として扱える (例: COMBINING ENCLOSING CIRCLE, U+20DD)

```swift
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
// enclosedEAcute is é⃝
```

regional indicator symbolsに対応するUnicodeスカラは、単一のCharacter型の値を作るために、pairsに結合される

例：
REGIONAL INDICATOR SYMBOL LETTER U (U+1F1FA)と、REGIONAL INDICATOR SYMBOL LETTER S (U+1F1F8)との組み合わせ

```swift
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS is 🇺🇸
```

## Counting Characters
Stringの中のCharacterの数を調べたいなら、String.charactersのcountプロパティを使う

```swift
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// Prints "unusualMenagerie has 40 characters"
```


ただし、SwiftのCharacterはextended grapheme clustersを使っているので、Stringの結合/修正しても、character.countに影響を与えないこともある

例：
4文字の単語"word"にCOMBINING ACUTE ACCENT (U+0301)を追加しても、結果のcharacters.countは4のまま。4文字目は、eでなくéになっている

```swift
var word = "cafe"
print("the number of characters in \(word) is \(word.characters.count)")
// Prints "the number of characters in cafe is 4"
 
word += "\u{301}"    // COMBINING ACUTE ACCENT, U+0301

print("the number of characters in \(word) is \(word.characters.count)")
// Prints "the number of characters in café is 4"
```

Extended grapheme clustersは1つまたは複数のUnicodeScalarから構成されるので、違う文字、さらには同じ文字の違う表現は、使うメモリの量が異なる可能性がある。

たとえ同じ文字列の中であっても、各charactersがおなじ量のメモリを使うわけではなので、文字数はString全てをiterateしないと、extended grapheme clusterの境界がわからず、文字数を数えられない

特に、長いString値を扱う時には、.charactersプロパティは、String中の全てのUnicodeスカラをイテレートしなきゃ決定できないことを知っておいてください

NSString型の`.length`は、UTF-16に基づいているので、`.characters.count`の結果は、(NSString).lengthの結果と違うこともある。

## Accessing and Modifying a String
メソッド、プロパティ、サブスクリプト等でStringを取得・修正できる

### String Indices
各String型の値には、関連づいたString.Index型があって、各Characterの位置に対応している

上で述べたように、各Characterの必要とするメモリ容量がわからないので、各UnicodeScalarを先頭もしくは末尾からiterateしないと、どのCharacterがその位置にあるのか特定できない
そのため、SwiftのStringでは、Integerでインデックス出来ない

`.startIndex`プロパティはStringの先頭のCharacterの位置を、`.endIndex`プロパティはStringの末尾のCharacterの次の位置を表す。よって、`.endIndex`はsubscriptとして有効ではない。(例2参照)
Stringが空の時、`.startIndex`は`.endIndex`と等しい

`String.Index`の値は、`predecessor()`メソッドを呼ぶと直前の文字に、`successor()`メソッドを呼ぶと直後の文字にアクセスできる
Stringの文字は全て、他のIndexから、このメソッドを繋げるか、もしくは`advancedBy(_:)`メソッドを使ってアクセスできる。
もしStringの範囲外のindexを指定すると、runtime errorが発生する

特定のindexにあるCharacterは、subscriptでアクセスできる

```swift
let greeting = "Guten Tag!"
greeting[greeting.startIndex]
// G
greeting[greeting.endIndex.predecessor()]
// !
greeting[greeting.startIndex.successor()]
// u
let index = greeting.startIndex.advancedBy(7)
greeting[index]
// a
```

範囲外にアクセスするとエラー

```swift
greeting[greeting.endIndex] // error
greeting.endIndex.successor() // error
```

`.characters.indices`プロパティは、各Characterにアクセスするためのindexesの`Range`を生成するので、各Characterを読み出せる

```swift
for index in greeting.characters.indices {
    print("\(greeting[index]) ", terminator: "")
}
// prints "G u t e n   T a g ! "
```

### Inserting and Removing

Stringの特定の位置に文字を挿入するには、`insert(_:atIndex:)`メソッドを使う

```swift
var welcome = "hello"
welcome.insert("!", atIndex: welcome.endIndex)
// welcome now equals "hello!"
```

特定の位置に別の文字列を挿入するには、`insertContentsOf(_:at:)`メソッドを使う

```swift
welcome.insertContentsOf(" there".characters, at: welcome.endIndex.predecessor())
// welcome now equals "hello there!"
```

特定の位置のCharacterを削除するには、`removeAtIndex(_:)`メソッドを使う

```swift
welcome.removeAtIndex(welcome.endIndex.predecessor())
// welcome now equals "hello there"
```

特定の範囲のサブ文字列を削除するには、`removeRange(_:)`メソッドを使う

```swift
let range = welcome.endIndex.advancedBy(-6)..<welcome.endIndex
welcome.removeRange(range)
// welcome now equals "hello"
```

## Comparing Strings

Swiftには、テキストの値を比較する方法が３つある
- 文字・文字列の等しさ
- prefixの等しさ
- suffixの等しさ

### String and Character Equality
文字・文字列が等しいかは、`==`, `!=`で評価できる（参照：[比較演算子](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID70)）

```swift
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
    print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
```

２つの文字/文字列は、extended grapheme clustersが正準等価(canonically equivalent)なときに等しいとみなされる。extended grapheme clustersは、言語的意味、見た目が同じなら、裏では違うUnicode scalarsからできていても、正準等価である

例：
LATIN SMALL LETTER E WITH ACUTE (U+00E9)は
LATIN SMALL LETTER E (U+0065) + COMBINING ACUTE ACCENT (U+0301)
と等価
これらはともにéを表す。

```swift
// "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
 
// "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
 
if eAcuteQuestion == combinedEAcuteQuestion {
    print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
```

逆に、アメリカで使われるような、
LATIN CAPITAL LETTER A (U+0041, or "A")
と、ロシアで使われるような
CYRILLIC CAPITAL LETTER A (U+0410, or "А")
は等価ではない。
これらは見た目は似ているが、言語的な意味は異なる。

```swift
let latinCapitalLetterA: Character = "\u{41}"
 
let cyrillicCapitalLetterA: Character = "\u{0410}"
 
if latinCapitalLetterA != cyrillicCapitalLetterA {
    print("These two characters are not equivalent")
}
// Prints "These two characters are not equivalent"
```

Note: 
Swiftにおける文字・文字列の比較は、localeによって出来たり出来なかったりするようなものではないです


### Prefix and Suffix Equality
文字列が特定の接頭辞・接尾辞を持っているかは、`hasPrefix(_:)`メソッド、`hasSuffix(_:)`メソッドを用いる。共にStringを受け取り、Boolを返す

下記の例は、ロミオとジュリエット/シェイクスピアのはじめの２幕の各シーンの舞台を表すStringのArray

```swift
let romeoAndJuliet = [
    "Act 1 Scene 1: Verona, A public place",
    "Act 1 Scene 2: Capulet's mansion",
    "Act 1 Scene 3: A room in Capulet's mansion",
    "Act 1 Scene 4: A street outside Capulet's mansion",
    "Act 1 Scene 5: The Great Hall in Capulet's mansion",
    "Act 2 Scene 1: Outside Capulet's mansion",
    "Act 2 Scene 2: Capulet's orchard",
    "Act 2 Scene 3: Outside Friar Lawrence's cell",
    "Act 2 Scene 4: A street in Verona",
    "Act 2 Scene 5: Capulet's mansion",
    "Act 2 Scene 6: Friar Lawrence's cell"
]
```

`hasPrefix(_:)`メソッドを使えば、Act 1のシーンの数を数えられる

```swift
var act1SceneCount = 0
for scene in romeoAndJuliet {
    if scene.hasPrefix("Act 1 ") {
        act1SceneCount += 1
    }
}
print("There are \(act1SceneCount) scenes in Act 1")
// Prints "There are 5 scenes in Act 1"
```

同様に、`hasSuffix(_:)`メソッドを使えば、Capulet’s mansionの中や、Friar Lawrence’s cellの近くのシーンの数を数えられる

```swift
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
    if scene.hasSuffix("Capulet's mansion") {
        mansionCount += 1
    } else if scene.hasSuffix("Friar Lawrence's cell") {
        cellCount += 1
    }
}
print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// Prints "6 mansion scenes; 2 cell scenes"
```

Note:

`hasPrefix(_:)`、`hasSuffix(_:)`メソッドは、各文字列のextended grapheme clusters同士で、文字単位の正準等価(canonical equivalence)の比較を行う（String and Character Equality参照）

## Unicode Representations of Strings
Unicode文字列がテキストファイル等に書きだされたら、文字列中のUnicodeScalarsは何らかのUnicodeで使えるエンコーディング形式にエンコードされる。
各形式は、code unitとして知られる小さなchunkに文字列をエンコードする。
UTF-8形式(8-bit code unitsとして文字列をエンコードする)や、UTF-16形式(16-bit code unitsとして文字列をエンコードする)や、UTF-32形式(32-bit code unitsとして文字列をエンコードする)なども含む。

SwiftにはいくつかUnicode表現にアクセスする方法がある
`for-in`構文でstring全てiterateすれば、各Unicode extended grapheme clusterにアクセスできる(Working with Characters参照)

他にも、3つのUnicode準拠の表現のいずれかでもStringの値にアクセスできる

- UTF-8のcode unitの集まり
- UTF-16のcode unitの集まり
- 21-bitのUnicodeScalar値(UTF-32形式と等価)

それぞれ、`.utf8`プロパティ、`utf16`プロパティ、`.unicodeScalars`プロパティでアクセスできる

以下に示す各例は、"Dog‼🐶"の異なる表現である。これは、
D,
o,
g,
‼ (DOUBLE EXCLAMATION MARK, or Unicode scalar U+203C),
🐶 character (DOG FACE, or Unicode scalar U+1F436)
からできている

```swift
let dogString = "Dog‼🐶"
```

### UTF-8 Representation
`.utf8`プロパティをiterateすれば、UTF-8表現を得られる。これはString.UTF8View型で、UTF8表現の各バイト対応するUInt8型(unsigned 8-bit)の値の集まり

![Character-utf8-map](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/UTF8_2x.png)

```swift
for codeUnit in dogString.utf8 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 226 128 188 240 159 144 182
```

上の例では、最初の3つの数字(68, 111, 103)がD, o, gを表す。これはASCII表現と同じ。
その次の３つのcodeUnitの値(226, 128, 188)は、3バイトの、DOUBLE EXCLAMATION MARKのUTF-8表現で、最後の4つのcodeUnitの値(240, 159, 144, 182)は4バイトの、DOG FACEのUTF-8表現。


### UTF-16 Representation
`.utf16`プロパティをiterateすれば、UTF-16表現を得られる。これはString.UTF16View型で、UTF16表現の各16-bitのcode unitに対応するUInt16型(unsigned 16-bit)の値の集まり

![Character-utf16-map](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/UTF16_2x.png)

```swift
for codeUnit in dogString.utf16 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 8252 55357 56374
```

繰り返すが、はじめ３つのcodeUnitの値(68, 111, 103)はD、o、gを表し、これはUTF-8の値と同じ。(何故ならUnicodeScalarはASCII文字を表現しているから)

4番目のcodeUnitの値(8252)は10進数で、16進数の203Cと等価。つまりUnicodeScalarの"U+203C"であるDOUBLE EXCLAMATION MARKを表す。これはUTF-16では単一のcode unitで表現される

5, 6番目のcodeUnitの値(55357, 56374)はDOG FACEのサロゲートペア(1つの文字を表す連続した2つのcode pointのペア)。
ここでは、high-surrogate valueはU+D83D(10進数で55357)、low-surrogate valueはU+DC36(10進数で56374)


### Unicode Scalar Representation

`.unicodeScalars`プロパティをiterateすれば、Unicode scalar表現を得られる。これはUnicodeScalarView型で、UnicodeScalar型の値の集まり

各UnicodeScalarは`.value`プロパティを持ち、scalarの21-bitの値を返す。これはUInt32型として渡される

![Character-unicodeScalar-map](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/UnicodeScalar_2x.png)

```swift
for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ", terminator: "")
}
print("")
// 68 111 103 8252 128054
```

はじめ３つのUnicodeScalarの値(68, 111, 103)のvalueプロパティは、ここでもD、o、gを表す

4番目のcodeUnitの値(8252)は、ここでも、10進数で16進数の203Cと等価で、UnicodeScalarの"U+203C"であるDOUBLE EXCLAMATION MARKを表す。

5, 6番目のUnicodeScalarの`.value`プロパティ(128054)は、10進数で、16進数の1F436と等価。これはUnicode scalarのU+1F436、つまりDOG FACEを表す。

他にも、`.value`プロパティを得る方法としてだが、各UnicodeScalar値は、string interpolationみたいに新しいStringを作るのにも使える

```swift
for scalar in dogString.unicodeScalars {
    print("\(scalar) ")
}
// D
// o
// g
// ‼
// 🐶
```