Swiftで範囲を作成するにはどうすればよいですか?



How Create Range Swift



解決:

スイフト4用にアップデート

Swiftの範囲はより複雑ですNSRangeであり、Swift 3では簡単になりませんでした。この複雑さの背後にある理由を理解したい場合は、これとこれを読んでください。それらを作成する方法と、いつ使用するかを説明します。



クローズドレンジ:a ... b

この範囲演算子は、両方の要素を含むSwift範囲を作成します エレメントb、たとえbは、タイプの可能な最大値です(Int.max)。クローズドレンジには2つの異なるタイプがあります。ClosedRangeとCountableClosedRange。

1.1。ClosedRange

Swiftのすべての範囲の要素は比較可能です(つまり、Comparableプロトコルに準拠しています)。これにより、コレクションから範囲内の要素にアクセスできます。次に例を示します。



let myRange:ClosedRange = 1 ... 3 let myArray = ['a'、 'b'、 'c'、 'd'、 'e'] myArray [myRange] // ['b'、 'c'、 ' NS']

ただし、ClosedRangeはカウントできません(つまり、Sequenceプロトコルに準拠していません)。つまり、要素を反復処理することはできません。forループ。そのためには、CountableClosedRange。

2.2。CountableClosedRange

これは前のものと似ていますが、範囲を繰り返すこともできるようになりました。

let myRange:CountableClosedRange = 1 ... 3 let myArray = ['a'、 'b'、 'c'、 'd'、 'e'] myArray [myRange] // ['b'、 'c'、 ' d '] myRangeのインデックス{print(myArray [index])}

ハーフオープンレンジ:に..

この範囲演算子には要素が含まれますしかし いいえ エレメントNS。上記のように、ハーフオープン範囲には2つの異なるタイプがあります。範囲とCountableRange。



1.1。範囲

と同じようにClosedRangeでは、コレクションの要素にアクセスできます。範囲。例:

myRange:Range = 1とします。<3 let myArray = ['a', 'b', 'c', 'd', 'e'] myArray[myRange] // ['b', 'c']  

繰り返しになりますが、繰り返し処理することはできません。範囲は比較可能であり、ストライドできないためです。

2.2。CountableRange

CountableRangeは反復を許可します。

myRange:CountableRange = 1とします。<3 let myArray = ['a', 'b', 'c', 'd', 'e'] myArray[myRange] // ['b', 'c'] for index in myRange { print(myArray[index]) }  

NSRange

あなたはまだ使うことができます(しなければなりません)NSRangeはSwiftで時々(たとえば、属性付き文字列を作成するとき)、その作成方法を知っておくと役に立ちます。

myNSRange = NSRange(location:3、length:2)

これは場所であり、 長さ 、開始インデックスと終了インデックスではありません。ここでの例は、Swiftの範囲と意味が似ています3.。<5. However, since the types are different, they are not interchangeable.

文字列のある範囲

NS... と..< range operators are a shorthand way of creating ranges. For example:

myRange = 1とします。<3  

同じ範囲を作成するための長い道のりは

let myRange = CountableRange(uncheckedBounds:(lower:1、upper:3))// 1.。<3  

ここのインデックスタイプは次のとおりです。Int。それはうまくいきませんただし、文字列は文字で構成されており、すべての文字が同じサイズであるとは限らないためです。 (詳細については、これをお読みください。)たとえば、のような絵文字は、文字「b」よりも多くのスペースを必要とします。

NSRangeの問題

試してみてくださいNSRangeと絵文字付きのNSStringを使用すると、意味がわかります。頭痛。

let myNSRange = NSRange(location:1、length:3)let myNSString:NSString = 'abcde' myNSString.substring(with:myNSRange)// 'bcd' let myNSString2:NSString = 'acde' myNSString2.substring(with:myNSRange) // 'c''d'はどこにありますか!?

スマイリーフェイスは、格納するのに2つのUTF-16コードユニットを必要とするため、「d」を含まないという予期しない結果が生じます。

スウィフトソリューション

このため、SwiftStringsでは範囲ではなく範囲。文字列インデックスは特定の文字列に基づいて計算されるため、絵文字や拡張書記素クラスターがあるかどうかがわかります。

var myString = 'abcde' let start = myString.index(myString.startIndex、offsetBy:1)let end = myString.index(myString.startIndex、offsetBy:4)let myRange = start.。片側範囲:a ...そして... bおよび..  

Swift 4では、物事が少し単純化されました。範囲の開始点または終了点を推測できる場合はいつでも、省略できます。

Int

片側整数範囲を使用して、コレクションを反復処理できます。これがドキュメントからのいくつかの例です。

//名前の名前についてはインデックス2から配列の最後まで繰り返します[2 ...] {print(name)} //名前の名前については配列の最初からインデックス2まで繰り返します[... 2] {print(name)} //配列の先頭から、名前の名前のインデックス2までを繰り返します[..<2] { print(name) } // the range from negative infinity to 5. You can't iterate forward // over this because the starting point in unknown. let range = ...5 range.contains(7) // false range.contains(4) // true range.contains(-1) // true // You can iterate over this but it will be an infinate loop // so you have to break out at some point. let range = 5...  

これは文字列範囲でも機能します。あなたが範囲を作っているならstr.startIndexまたはstr.endIndexの一方の端は、省略できます。コンパイラはそれを推測します。

与えられた

var str = 'こんにちは、遊び場' let index = str.index(str.startIndex、offsetBy:5)let myRange =.。 を使用して、インデックスからstr.endIndexに移動できます。..。

var str = 'こんにちは、遊び場' let index = str.index(str.endIndex、offsetBy:-10)let myRange = index ... //遊び場

参照:

  • String.IndexはSwiftでどのように機能しますか
  • Swiftで文字列部分文字列はどのように機能しますか

ノート

  • ある文字列で作成した範囲を別の文字列で使用することはできません。
  • ご覧のとおり、Swiftでは文字列範囲が苦痛ですが、絵文字やその他のUnicodeスカラーをより適切に処理できる可能性があります。

さらなる研究

  • 文字列範囲の例
  • 範囲演算子のドキュメント
  • 文字列と文字のドキュメント

Xcode8ベータ2•Swift3

let myString = 'Hello World' let myRange = myString.startIndex.。 

Xcode7•Swift2.0

let myString = 'Hello World' let myRange = Range(start:myString.startIndex、end:myString.startIndex.advancedBy(5))let mySubString = myString.substringWithRange(myRange)// Hello

または単に

let myString = 'Hello World' let myRange = myString.startIndex.。 

(1。。<10)

戻り値...

範囲= 1。<10