String.substringWithRangeをどのように使用しますか?(または、SwiftでRangesはどのように機能しますか?)


266

StringSwift でaの部分文字列を取得する方法はまだわかりません。

var str =Hello, playground”
func test(str: String) -> String {
 return str.substringWithRange( /* What goes here? */ )
}
test (str)

SwiftでRangeを作成できません。プレイグラウンドでのオートコンプリートはあまり役に立ちません-これはそれが示唆していることです:

return str.substringWithRange(aRange: Range<String.Index>)

Swift標準リファレンスライブラリに役立つ情報は見つかりませんでした。ここに別の野生の推測がありました:

return str.substringWithRange(Range(0, 1))

この:

let r:Range<String.Index> = Range<String.Index>(start: 0, end: 2)
return str.substringWithRange(r)

他の回答(Swift Stringの文字のインデックスの検索)を見たことがあります。これStringはのブリッジタイプであるためNSString、「古い」メソッドは機能するはずですが、どのように機能するかは明確ではありません。たとえば、これも機能しません(有効な構文ではないようです):

let x = str.substringWithRange(NSMakeRange(0, 3))

考え?


最後の例が機能しないとはどういう意味ですか?エラーが発生するか、予期しない値が返されますか?
67チェリー2014年

添え字表記を要求するrdar:// 17158813を複製してくださいopenradar.appspot.com/radar?id=6373877630369792
Rob Napier

回答:


259

substringWithRangeメソッドを使用できます。開始と終了のString.Indexを取ります。

var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex, end: str.endIndex)) //"Hello, playground"

開始インデックスと終了インデックスを変更するには、advancedBy(n)を使用します。

var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex.advancedBy(2), end: str.endIndex.advancedBy(-1))) //"llo, playgroun"

NSRangeでNSStringメソッドを使用することもできますが、次のようなNSStringを使用していることを確認する必要があります。

let myNSString = str as NSString
myNSString.substringWithRange(NSRange(location: 0, length: 3))

注:JanX2で述べたように、この2番目の方法は、Unicode文字列では安全ではありません。


5
うん。今のところ、必要に応じてNSStringにブリッジし続けます。Swiftの文字列はまだ不完全なようです
Connor

14
これは安全ではありません!StringとNSStringへのインデックスは交換可能であると想定しています。そうではありません。文字列へのインデックスはUnicodeコードポイントを参照し、NSStringへのインデックスはUTF-16コード単位を参照します!絵文字でお試しください。
JanX2 2014年

3
文字列へのインデックスはUnicodeコードポイントを参照しないことに注意してください。それらは、ユーザーが認識する文字を参照していると考えてください。
JanX2 2014

2
ここで正しい答えは何ですか?呼び出しadvanceとは、おそらく長い文字列全体を繰り返し処理する必要があることを意味します。しかし、NSRangeを形成してNSStringを明示的に使用するのは危険ですか?あと何?
マット2014年

1
ありがとう、m8。このSwiftへの移行は、Objective-Cを4年間だけ行った後で、厄介なものになっています。
フェリペ

162

スウィフト2

シンプルな

let str = "My String"
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)]
//"Strin"

スウィフト3

let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)

str[startIndex...endIndex]       // "Strin"
str.substring(to: startIndex)    // "My "
str.substring(from: startIndex)  // "String"

スウィフト4

substring(to:)およびでsubstring(from:)は非推奨ですSwift 4

String(str[..<startIndex])    // "My "
String(str[startIndex...])    // "String"
String(str[startIndex...endIndex])    // "Strin"

2
この。混乱するので、使用する前にインデックスを見つける必要があります。なぜ実現するのにそんなに時間がかかったのかわからないが、人間のような貢献に感謝している。
Warpzit 2017年

1
Swift 4では、部分文字列操作は文字列ではなく、部分文字列型のインスタンスを返します。長期保存のために結果を文字列に変換する必要があります。let newString = String(substring)
phnmnn '31年

43

注:@airspeedswiftは、このアプローチのトレードオフ、特に隠されたパフォーマンスへの影響について、非常に洞察に満ちたポイントを示します。文字列は単純な獣ではなく、特定のインデックスに到達するにはO(n)時間かかる場合があります。つまり、添え字を使用するループはO(n ^ 2)になる可能性があります。あなたは警告されました。

subscript範囲advancedBy()を取得し、目的の場所に移動するために使用する新しい関数を追加するだけです。

import Foundation

extension String {
    subscript (r: Range<Int>) -> String {
        get {
            let startIndex = self.startIndex.advancedBy(r.startIndex)
            let endIndex = startIndex.advancedBy(r.endIndex - r.startIndex)

            return self[Range(start: startIndex, end: endIndex)]
        }
    }
}

var s = "Hello, playground"

println(s[0...5]) // ==> "Hello,"
println(s[0..<5]) // ==> "Hello"

(これは間違いなく言語の一部である必要があります。rdar:// 17158813を複製してください)

楽しみのため+に、インデックスに演算子を追加することもできます:

func +<T: ForwardIndex>(var index: T, var count: Int) -> T {
  for (; count > 0; --count) {
    index = index.succ()
  }
  return index
}

s.substringWithRange(s.startIndex+2 .. s.startIndex+5)

(これが言語の一部であるかどうかはまだわかりません。)


2
パフォーマンス上の理由から、整数インデックスではなくString.Indexをできるだけ使用する必要があります。整数インデックスからString.Indexへの変換はすべて、シークする文字列を処理する必要があります。
JanX2 2014年

11
@AndrewDunnこれは時期尚早の最適化ではありません。整数インデックスからString.Indexへの各変換はO(n)であり、O(1)ではありません!名前空間advance<T>(…)内のコメントを読んでくださいSwift
JanX2 2014

1
String実装全体は、を使用して行われString.Indexます。この場合、すべてを簡単に保つための最適化ではありません。あらゆる場所でintとString.Indexをやり取りする必要があると、混乱につながります。
chakrit 2014

@chakrit使用する必要があるインデックスが(String.Indexes ではなく)まだ整数でない場合にのみ、これはよくあるケースです。これらのすべての文字列処理メソッドがIntsで機能することを望んでもかまいません。そして、あなたはそれをString.Indexesあなたが言及した混乱につながるそれに収束させなければなりません。
Rasto 2014年

興味のある読者は、ExSwift github.com/pNre/ExSwift
AsTeR

42

私が書いている時点では、Swift 4.2と完全に互換性のある拡張機能はありません。そのため、考えられるすべてのニーズをカバーする拡張機能を以下に示します。

extension String {
    func substring(from: Int?, to: Int?) -> String {
        if let start = from {
            guard start < self.count else {
                return ""
            }
        }

        if let end = to {
            guard end >= 0 else {
                return ""
            }
        }

        if let start = from, let end = to {
            guard end - start >= 0 else {
                return ""
            }
        }

        let startIndex: String.Index
        if let start = from, start >= 0 {
            startIndex = self.index(self.startIndex, offsetBy: start)
        } else {
            startIndex = self.startIndex
        }

        let endIndex: String.Index
        if let end = to, end >= 0, end < self.count {
            endIndex = self.index(self.startIndex, offsetBy: end + 1)
        } else {
            endIndex = self.endIndex
        }

        return String(self[startIndex ..< endIndex])
    }

    func substring(from: Int) -> String {
        return self.substring(from: from, to: nil)
    }

    func substring(to: Int) -> String {
        return self.substring(from: nil, to: to)
    }

    func substring(from: Int?, length: Int) -> String {
        guard length > 0 else {
            return ""
        }

        let end: Int
        if let start = from, start > 0 {
            end = start + length - 1
        } else {
            end = length - 1
        }

        return self.substring(from: from, to: end)
    }

    func substring(length: Int, to: Int?) -> String {
        guard let end = to, end > 0, length > 0 else {
            return ""
        }

        let start: Int
        if let end = to, end - length > 0 {
            start = end - length + 1
        } else {
            start = 0
        }

        return self.substring(from: start, to: to)
    }
}

そして、あなたは使うことができます:

let string = "Hello,World!"

string.substring(from: 1, to: 7)あなたを取得します: ello,Wo

string.substring(to: 7)あなたを取得します: Hello,Wo

string.substring(from: 3)あなたを取得します: lo,World!

string.substring(from: 1, length: 4)あなたを取得します: ello

string.substring(length: 4, to: 7)あなたを取得します: o,Wo

substring(from: Int?, length: Int)ゼロからの開始をサポートするように更新されました。


これは絵文字と拡張書記素クラスタをどのように処理しますか?(私は自分でテストする必要がありますが、現時点では便利ではありません。)
Suragch

2
@Suragchそれはそれを処理しますOK:"Hello😇😍😘😎📸📀💾∝ℵℶ≹".substring(from: 4, to: 14)私たちに与えます:o😇😍😘😎📸📀💾∝ℵℶ
冬の

しかし、それらは通常の文字のように見えます。👩‍👩‍👧‍👦やlikeなどの絵文字を使用してみてください
Supuhstar

31

SWIFT 2.0

シンプル:

let myString = "full text container"
let substring = myString[myString.startIndex..<myString.startIndex.advancedBy(3)] // prints: ful

SWIFT 3.0

let substring = myString[myString.startIndex..<myString.index(myString.startIndex, offsetBy: 3)] // prints: ful

SWIFT 4.0

部分文字列操作は、文字列ではなく、部分文字列型のインスタンスを返します。

let substring = myString[myString.startIndex..<myString.index(myString.startIndex, offsetBy: 3)] // prints: ful

// Convert the result to a String for long-term storage.
let newString = String(substring)

4
Xcode 8ベータ6以降、残念ながらSwift 3との互換性がなくなりました
Ben Morrow

1
私のために働く。Xcode 8、Swift3。MacOS Sierraのベータ版ではありません。text[text.startIndex..<text.index(text.startIndex, offsetBy: 2)]
ホセ・ラミレス

18

正しい構文が見つかれば、ここでのどの回答よりもはるかに簡単です。

[と]を取り除きたい

let myString = "[ABCDEFGHI]"
let startIndex = advance(myString.startIndex, 1) //advance as much as you like
let endIndex = advance(myString.endIndex, -1)
let range = startIndex..<endIndex
let myNewString = myString.substringWithRange( range )

結果は「ABCDEFGHI」になります。startIndexおよびendIndexは、

let mySubString = myString.substringFromIndex(startIndex)

等々!

PS:備考に示されているように、xcode 7とiOS9に付属しているswift 2には構文の変更があります!

このページをご覧ください


はい、デバッガーで同じ問題が何度か発生し、正しい文字列が表示されませんでしたか?
user1700737 2014年

/ Date(147410000000)/のような文字列があります。インデックスを指定する代わりに、どのようにして値を取得できますか?rangeOfString( "(")とrangeOfString( ")")を使用して値を取得する必要があります。結果は147410000000になるはずです。ホーはそれを取得できます
iPhone Guy

それはそれほど難しくありません:var str = "/ Date(147410000000)/。" var range = str.rangeOfString( "(")!. endIndex .. <str.rangeOfString( ")")!. startIndex let myNewString = str.substringWithRange(range)
user1700737

4
Xcode 7ベータ6のadvance(myString.endIndex, -1)構文がmyString.endIndex.advancedBy(-1)
l --marc lに

16

たとえば、私のフルネームで名(最初のスペースまで)を見つけるには:

let name = "Joris Kluivers"

let start = name.startIndex
let end = find(name, " ")

if end {
    let firstName = name[start..end!]
} else {
    // no space found
}

startおよびendString.Indexここにあり、を作成するためRange<String.Index>に使用され、添え字アクセサーで使用されます(元の文字列にスペースがまったくある場合)。

String.Index開始ポストで使用される整数位置から直接を作成するのは困難です。これは、私の名前では、各文字のサイズがバイトで等しいためです。ただし、他の言語で特殊なアクセントを使用する文字は、さらに数バイトを使用する可能性があります(使用するエンコードによって異なります)。それで、整数は何バイトを参照するべきですか?

String.Indexメソッドsuccを使用して既存のpredコードから新しいコードを作成することが可能であり、これにより、エンコードの次のコードポイントに到達するために正しいバイト数がスキップされます。ただし、この場合、文字列の最初のスペースのインデックスを検索して終了インデックスを見つける方が簡単です。


16

StringはNSStringのブリッジ型であるため、「古い」メソッドは機能するはずですが、どのように機能するかは明確ではありません。たとえば、これも機能しません(有効な構文ではないようです)。

 let x = str.substringWithRange(NSMakeRange(0, 3))

私にとって、それはあなたの質問の本当に興味深い部分です。文字列 NSStringにブリッジされるため、ほとんどの NSStringメソッド文字列に対して直接機能します。思いっきり自由に使えます。したがって、たとえば、これは期待どおりに機能します。

// delete all spaces from Swift String stateName
stateName = stateName.stringByReplacingOccurrencesOfString(" ", withString:"")

しかし、よくあることですが、「モジョが動作しましたが、動作しません。」たまたま、同じ名前のSwiftメソッドが並列に存在するというまれなケースの1つを選択しました。そのような場合、SwiftメソッドがObjective-Cメソッドを覆い隠します。したがって、と言うとstr.substringWithRange、SwiftはNSStringメソッドではなくSwiftメソッドを意味していると見なします。その場合、Swiftメソッドはを想定しているため、Range<String.Index>それらの1つを作成する方法がわからないためです。

簡単な方法は、明示的にキャストすることで、Swiftがこのように影を落とさないようにすることです。

let x = (str as NSString).substringWithRange(NSMakeRange(0, 3))

ここでは、余計な作業は必要ありません。「キャスト」は「変換」を意味しません。文字列事実上NSStringです。この1行のコードの目的で、この変数を確認する方法をSwiftに伝えているだけです。

この全体の本当に奇妙な部分は、このすべての問題を引き起こすSwiftメソッドが文書化されていないことです。それがどこに定義されているのか私にはわかりません。NSStringヘッダーにも、Swiftヘッダーにもありません。


ただし、バグを報告することをお勧めします。Appleは「餌を釣るか、切り取る」べきである-を構築する方法を提供するRange<String.Index>か、この文書化されていない方法を邪魔にならないようにする。
マット

くそーこれは便利です。ドキュメンテーションが言っていることにもかかわらず、私はこれを読むまで何が悪いのか理解していませんでした。現在ソートされています:)
Jon M

13

新しいXcode 7.0で使用

//: Playground - noun: a place where people can play

import UIKit

var name = "How do you use String.substringWithRange?"
let range = name.startIndex.advancedBy(0)..<name.startIndex.advancedBy(10)
name.substringWithRange(range)

//OUT:

ここに画像の説明を入力してください


2
.advancedBy(0) startIndexには必要ありません。
Mat0 2016年

12

簡単に言えば、これは現在Swiftでは本当に難しいことです。私の直感は、Appleがこのようなことのための便利なメソッドでやるべき仕事がまだたくさんあるということです。

String.substringWithRange()Range<String.Index>パラメータを期待しており、私が知る限り、String.Index型のジェネレータメソッドはありません。ただいまString.Index値からバックaString.startIndexaString.endIndex、コール.succ()または.pred()それらの上に、しかしの狂気という。

古き良きInts をとるStringクラスの拡張はどうですか?

extension String {
    subscript (r: Range<Int>) -> String {
        get {
            let subStart = advance(self.startIndex, r.startIndex, self.endIndex)
            let subEnd = advance(subStart, r.endIndex - r.startIndex, self.endIndex)
            return self.substringWithRange(Range(start: subStart, end: subEnd))
        }
    }
    func substring(from: Int) -> String {
        let end = countElements(self)
        return self[from..<end]
    }
    func substring(from: Int, length: Int) -> String {
        let end = from + length
        return self[from..<end]
    }
}

let mobyDick = "Call me Ishmael."
println(mobyDick[8...14])             // Ishmael

let dogString = "This 🐶's name is Patch."
println(dogString[5..<6])               // 🐶
println(dogString[5...5])              // 🐶
println(dogString.substring(5))        // 🐶's name is Patch.
println(dogString.substring(5, length: 1))   // 🐶

更新: Swiftベータ4は以下の問題を解決します!

[ベータ3以前]の現状では、Swiftネイティブの文字列でさえ、Unicode文字の処理に問題があります。上記の犬のアイコンは機能しましたが、以下は機能しません。

let harderString = "1:1️⃣"
for character in harderString {
    println(character)
}

出力:

1
:
1
️
⃣

1
奇妙なことに、コアのSwiftクラスには基本的な機能が多くないようです。Appleが継続的にFoundationクラスを参照して単純なタスクを実行することを望んでいるとは思えません。
bluedevil2k 2014年

1
完全に。Swiftは基本的に暗闇の中で開発され、誰もが「単純なタスク」の定義が異なることを覚えておいてください。
ネイト・クック

@ JanX2-ありがとうございます。あなたの言うとおりです。とのシームレスなブリッジによりNSString、私はSwiftネイティブのStringメソッドのみを使用していると思いましたmyString as NSString
ネイト・クック

現在、Swiftネイティブの文字列処理にもいくつかのUnicodeバグがあります。最後にある私のメモを参照してください。
ネイト・クック

@NateCookその問題についてレーダーを提出していただけませんか?
JanX2 2014年

11

この拡張機能を使用して改善することができます substringWithRange

Swift 2.3

extension String
{   
    func substringWithRange(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(end))
        return self.substringWithRange(range)
    }

    func substringWithRange(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(start + location))
        return self.substringWithRange(range)
    }
}

スウィフト3

extension String
{
    func substring(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: end)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }

    func substring(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: start + location)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }
}

使用法:

let str = "Hello, playground"

let substring1 = str.substringWithRange(0, end: 5) //Hello
let substring2 = str.substringWithRange(7, location: 10) //playground

7

Swift 2.0で部分文字列を取得する方法のサンプルコード

(i)開始インデックスの部分文字列

入力:-

var str = "Swift is very powerful language!"
print(str)

str = str.substringToIndex(str.startIndex.advancedBy(5))
print(str)

出力:-

Swift is very powerful language!
Swift

(ii)特定のインデックスの部分文字列

入力:-

var str = "Swift is very powerful language!"
print(str)

str = str.substringFromIndex(str.startIndex.advancedBy(6)).substringToIndex(str.startIndex.advancedBy(2))
print(str)

出力:-

Swift is very powerful language!
is

お役に立てれば幸いです。


7

少ないコードで簡単に解決できます。

他のほとんどすべての言語が持つ基本的なsubStringingを含む拡張を作成します。

extension String {
    func subString(start: Int, end: Int) -> String {
        let startIndex = self.index(self.startIndex, offsetBy: start)
        let endIndex = self.index(startIndex, offsetBy: end)

        let finalString = self.substring(from: startIndex)
        return finalString.substring(to: endIndex)
    }
}

単にこれを

someString.subString(start: 0, end: 6)

1
「end」パラメータは実際にはここでは長さを意味するので、名前をそのように変更する必要があると思います。
Jovan Jovanovski、2017

長さを使用するのはかなり混乱すると思います。これは実際には、subStringの結果の実際の長さではなく、subStringを置きたい場所の「終わり」です。
Oliver Dixon

6

これは私の遊び場で動作します:)

String(seq: Array(str)[2...4])

実際、これは電話をかけるよりも効率的ですadvance
Erik Aigner

2
Xcode 7(Swift 2)プレイグラウンドでは機能しませんが、これは機能します... 'var str = "Hello、playground"' String(Array(str.characters)[7])// "p" String(Array( str.characters)[7 ... 10])// "play" String(Array(str.characters)[7 .. <10])// "pla"
Vince O'Sullivan

6

Xcode 7用に更新されました。文字列拡張を追加します。

使用する:

var chuck: String = "Hello Chuck Norris"
chuck[6...11] // => Chuck

実装:

extension String {

    /**
     Subscript to allow for quick String substrings ["Hello"][0...1] = "He"
     */
    subscript (r: Range<Int>) -> String {
        get {
            let start = self.startIndex.advancedBy(r.startIndex)
            let end = self.startIndex.advancedBy(r.endIndex - 1)
            return self.substringWithRange(start..<end)
        }
    }

}

4

遊び場でこれを試してみてください

var str:String = "Hello, playground"

let range = Range(start:advance(str.startIndex,1), end: advance(str.startIndex,8))

それはあなたに「こんにちは、p」を与えます

ただし、これが非常に興味深いのは、最後のインデックスをプレイグラウンドの文字列よりも大きくすると、str:oの後に定義した文字列が表示されるということです。

Range()は一般的な関数のように見えるため、処理する型を知る必要があります。

それはまたあなたの遊び場に興味のある実際の文字列を与える必要があります。それは、変数名を含むすべての文字列を順番に保持しているように見えるためです。

そう

var str:String = "Hello, playground"

var str2:String = "I'm the next string"

let range = Range(start:advance(str.startIndex,1), end: advance(str.startIndex,49))

与え"ello、playgroundstrI'm次stringstr2"

str2がletで定義されている場合でも機能します

:)


Objective-Cに比べて冗長であることに同意しますが、すべて1行に収まるのでボーナスです。
Peter Roberts

さて、あなたが計算した範囲を与えられた部分文字列を実際に出力する1行がまだありません。私はあなたのロジックを使用してStringクラス拡張を作成する他のソリューションのいくつかが好きですが、拡張内にあります。それが最終的に私が行ったソリューションです。
ロデリックキャンベル2014

彼らはあなたが文字列の終わりを越えて行くことができるバグを修正しました。現在は、str.endIndexまでの値しか入力できません
Peter Roberts

4

ロブネイピアはすでに下付き文字を使用して素晴らしい答えを与えていました。しかし、範囲外のチェックがないため、欠点が1つありました。これはクラッシュする傾向があります。だから私は拡張子を変更し、ここにあります

extension String {
    subscript (r: Range<Int>) -> String? { //Optional String as return value
        get {
            let stringCount = self.characters.count as Int
            //Check for out of boundary condition
            if (stringCount < r.endIndex) || (stringCount < r.startIndex){
                return nil
            }
            let startIndex = self.startIndex.advancedBy(r.startIndex)

            let endIndex = self.startIndex.advancedBy(r.endIndex - r.startIndex)

            return self[Range(start: startIndex, end: endIndex)]
        }
    }
}

以下の出力

var str2 = "Hello, World"

var str3 = str2[0...5]
//Hello,
var str4 = str2[0..<5]
//Hello
var str5 = str2[0..<15]
//nil

だから私は常にかどうかを確認することをお勧めします

if let string = str[0...5]
{
    //Manipulate your string safely
}

そこにバグがあります-endIndexは、インデックス間の距離ではなく、endIndexだけによって進められるstartIndexである必要があります。
Aviad Ben Dov

3

ではSwift3

例:変数「Duke James Thomas」の場合、「James」を取得する必要があります。

let name = "Duke James Thomas"
let range: Range<String.Index> = name.range(of:"James")!
let lastrange: Range<String.Index> = img.range(of:"Thomas")!
var middlename = name[range.lowerBound..<lstrange.lowerBound]
print (middlename)

2

Rob Napierからページを取得して、これらのCommon String Extensionsの 2つを開発しました。

subscript (r: Range<Int>) -> String
{
    get {
        let startIndex = advance(self.startIndex, r.startIndex)
        let endIndex = advance(self.startIndex, r.endIndex - 1)

        return self[Range(start: startIndex, end: endIndex)]
    }
}

func subString(startIndex: Int, length: Int) -> String
{
    var start = advance(self.startIndex, startIndex)
    var end = advance(self.startIndex, startIndex + length)
    return self.substringWithRange(Range<String.Index>(start: start, end: end))
}

使用法:

"Awesome"[3...7] //"some"
"Awesome".subString(3, length: 4) //"some"

型推論RangeRange<String.Index>おかげで代わりに使用できます。
Dan Rosenstark、2014

2

これは、文字列から範囲を取得する方法です。

var str = "Hello, playground"

let startIndex = advance(str.startIndex, 1)
let endIndex = advance(startIndex, 8)
let range = startIndex..<endIndex
let substr = str[range] //"ello, pl"

重要な点は、整数ではなくString.Index型(これはAdvanceが返すものです)の値の範囲を渡すことです。

これが必要な理由は、Swiftの文字列にはランダムアクセスがないためです(基本的にUnicode文字の可変長のため)。あなたもできませんstr[1]。String.Indexは、内部構造で機能するように設計されています。

添え字付きの拡張を作成することもできます。これにより、整数の範囲を渡すことができます(たとえば、Rob Napierの回答を参照)。


2

私は何かPythonicを考え出そうとしました。

ここにあるすべての添え字は素晴らしいですが、単純なものが本当に必要なときは、通常、後ろから数えたいときです。 string.endIndex.advancedBy(-1)

これはnil、開始インデックスと終了インデックスの両方の値をサポートします。ここで、開始、終了のnil0のインデックスを意味しますstring.characters.count

extension String {
    var subString: (Int?) -> (Int?) -> String {
        return { (start) in
            { (end) in
                let startIndex = start ?? 0 < 0 ? self.endIndex.advancedBy(start!) : self.startIndex.advancedBy(start ?? 0)
                let endIndex = end ?? self.characters.count < 0 ? self.endIndex.advancedBy(end!) : self.startIndex.advancedBy(end ?? self.characters.count)

                return startIndex > endIndex ? "" : self.substringWithRange(startIndex ..< endIndex)
            }
        }
    }
}

let dog = "Dog‼🐶"
print(dog.subString(nil)(-1)) // Dog!!

編集

よりエレガントなソリューション:

public extension String {
    struct Substring {
        var start: Int?
        var string: String

        public subscript(end: Int?) -> String {
            let startIndex = start ?? 0 < 0 ? string.endIndex.advancedBy(start!) : string.startIndex.advancedBy(start ?? 0)
            let endIndex = end ?? string.characters.count < 0 ? string.endIndex.advancedBy(end!) : string.startIndex.advancedBy(end ?? string.characters.count)

            return startIndex > endIndex ? "" : string.substringWithRange(startIndex ..< endIndex)
        }
    }

    public subscript(start: Int?) -> Substring {
        return Substring(start: start, string: self)
    }
}

let dog = "Dog‼🐶"
print(dog[nil][-1]) // Dog!!

1

最初に範囲を作成し、次に部分文字列を作成します。次のfromIndex..<toIndexような構文を使用できます。

let range = fullString.startIndex..<fullString.startIndex.advancedBy(15) // 15 first characters of the string
let substring = fullString.substringWithRange(range)

1

以下は、迅速にURL全体からvideo-Idのみ.ie(6oL687G0Iso)を取得する例です

let str = "https://www.youtube.com/watch?v=6oL687G0Iso&list=PLKmzL8Ib1gsT-5LN3V2h2H14wyBZTyvVL&index=2"
var arrSaprate = str.componentsSeparatedByString("v=")
let start = arrSaprate[1]
let rangeOfID = Range(start: start.startIndex,end:start.startIndex.advancedBy(11))
let substring = start[rangeOfID]
print(substring)

1
let startIndex = text.startIndex
var range = startIndex.advancedBy(1) ..< text.endIndex.advancedBy(-4)
let substring = text.substringWithRange(range)

ここで見ることができる完全なサンプル



0

まあ、私は同じ問題を抱えており、「bridgeToObjectiveC()」関数で解決しました:

var helloworld = "Hello World!"
var world = helloworld.bridgeToObjectiveC().substringWithRange(NSMakeRange(6,6))
println("\(world)") // should print World!

この例では、NSMakeRangeと組み合わせたsubstringWithRangeが、インデックス6(文字 "W")で始まり、インデックス6 + 6の位置(文字 "!")で終わる文字列の一部を取得することに注意してください。

乾杯。


私はこれを嫌い、それはベータ4で私のために働いているように見える唯一のものです
ロデリック・キャンベル


0

がある場合NSRange、へのブリッジはNSStringシームレスに機能します。たとえば、私はいくつかの作業を行っていてUITextFieldDelegate、範囲を置き換えるかどうかを尋ねられたときにすぐに新しい文字列値を計算したいと思いました。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
    println("Got new string: ", newString)
}

0

シンプルな拡張のためにString

extension String {

    func substringToIndex(index: Int) -> String {
        return self[startIndex...startIndex.advancedBy(min(index, characters.count - 1))]
    }
}

0

パフォーマンスを気にしない場合...これはおそらくSwift 4で最も簡潔なソリューションです

extension String {
    subscript(range: CountableClosedRange<Int>) -> String {
        return enumerated().filter{$0.offset >= range.first! && $0.offset < range.last!}
            .reduce(""){$0 + String($1.element)}
    }
}

これにより、次のようなことが可能になります。

let myStr = "abcd"
myStr[0..<2] // produces "ab"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.