Swift 4で文字列スライスの添え字を使用するにはどうすればよいですか?


294

Swift 3で記述した次の簡単なコードがあります。

let str = "Hello, playground"
let index = str.index(of: ",")!
let newStr = str.substring(to: index)

Xcode 9ベータ5から、次の警告が表示されます。

' substring(to:)'は非推奨です:String'部分範囲範囲'演算子を使用してスライス添字を使用してください。

部分的な範囲を持つこのスライス添字は、Swift 4でどのように使用できますか?


var str = "Hello、playground" let indexcut = str.firstIndex(of: "、")print(String(str [.. <indexcut!]))print(String(str [indexcut!...]))
user1828845

回答:


375

片側は空にしておく必要があるため、「部分範囲」という名前を付けます。

let newStr = str[..<index]

同じことが演算子からの部分的な範囲を表しています。反対側は空のままにしてください:

let newStr = str[index...]

これらの範囲演算子はを返すことに注意してくださいSubstring。それを文字列に変換したい場合は、Stringの初期化関数を使用します。

let newStr = String(str[..<index])

新しい部分文字列の詳細については、こちらをご覧ください


8
str[..<index]を返しますSubstring。あなたがなりたいnewStrなら、Stringあなたは書く必要があります:let newStr = "\(str[..<index])"
Lindemann '21

12
Substringあなたが本当に達成しようとしているのはString初期化であるので、ローンで文字列補間を使用することはおそらく少し混乱します:let newStr = String(str[..<index])
ゲーリー

5
「インデックス」値が単なる整数であるコードを更新すると、エラーメッセージが表示されますCannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>'。そこではどのような種類の値を使用する必要がありますか?
ConfusionTowers

22
@ ConfusionTowers、Swiftの文字列インデックスは整数ではなく、バージョン4でも変更されていません。おそらくstr[..<str.index(str.startIndex, offsetBy: 8)]そのようなものが必要になるでしょう。str.indexは、の関数における線形時間演算であることを覚えておいてくださいoffsetBy
zneak

6
@zneakおそらくお望みでしょうstr.prefix(8)
Tim Vermeulen

264

部分文字列(Swift 3)を文字列スライス(Swift 4)に変換

Swift 3、4の例:

let newStr = str.substring(to: index) // Swift 3
let newStr = String(str[..<index]) // Swift 4

let newStr = str.substring(from: index) // Swift 3
let newStr = String(str[index...]) // Swift 4 

let range = firstIndex..<secondIndex // If you have a range
let newStr = = str.substring(with: range) // Swift 3
let newStr = String(str[range])  // Swift 4

5
パーフェクト、そして3つと4つの例を並べてくれてありがとう、私のプロジェクトの更新がずっと簡単になります!
イーサンパーカー

86

スイフト5、4

使用法

let text = "Hello world"
text[0] // H
text[...3] // "Hell"
text[6..<text.count] // world
text[NSRange(location: 6, length: 3)] // wor

コード

import Foundation

public extension String {
  subscript(value: Int) -> Character {
    self[index(at: value)]
  }
}

public extension String {
  subscript(value: NSRange) -> Substring {
    self[value.lowerBound..<value.upperBound]
  }
}

public extension String {
  subscript(value: CountableClosedRange<Int>) -> Substring {
    self[index(at: value.lowerBound)...index(at: value.upperBound)]
  }

  subscript(value: CountableRange<Int>) -> Substring {
    self[index(at: value.lowerBound)..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeUpTo<Int>) -> Substring {
    self[..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeThrough<Int>) -> Substring {
    self[...index(at: value.upperBound)]
  }

  subscript(value: PartialRangeFrom<Int>) -> Substring {
    self[index(at: value.lowerBound)...]
  }
}

private extension String {
  func index(at offset: Int) -> String.Index {
    index(startIndex, offsetBy: offset)
  }
}

14
この機能は、デフォルトの迅速な動作である必要があります。
Laimis

4
確かにPRこのスウィフトのlibに:D
OhadM

2
これはSwiftの最も醜い部分の修正です。
ドミトリー

@Dmitryこの回答には-2があるため、誰かが気に入らなかった。:D
dimpiax

添え字演算子はインデックス関数のO(n)の複雑さを隠すため、これは悪い答えです。優れたプログラミングAPIでは、添え字のみを使用して高速ルックアップを示します。
ラグナリウス

38

Swift 4/5の方が短い:

var string = "123456"
string = String(string.prefix(3)) //"123"
string = String(string.suffix(3)) //"456"

26

コードのSwift 4への変換は、次の方法でも行うことができます。

let str = "Hello, playground"
let index = str.index(of: ",")!
let substr = str.prefix(upTo: index)

以下のコードを使用して、新しい文字列を作成できます。

let newString = String(str.prefix(upTo: index))

17

substring(from:index) [index ...]に変換されます

サンプルを確認する

let text = "1234567890"
let index = text.index(text.startIndex, offsetBy: 3)

text.substring(from: index) // "4567890"   [Swift 3]
String(text[index...])      // "4567890"   [Swift 4]

1
文字はSwift 4では非推奨です
。Swift4の

これは私を助けました。tnx
user1105951

17

Swift5

(Javaの部分文字列メソッド):

extension String {
    func subString(from: Int, to: Int) -> String {
       let startIndex = self.index(self.startIndex, offsetBy: from)
       let endIndex = self.index(self.startIndex, offsetBy: to)
       return String(self[startIndex...endIndex])
    }
}

使用法:

var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels

2
それでもスウィフト5.私は(サブストリングのJavaのスタイルを探していたで動作fromするto-1例えば、"Hello".substring(1,4)リターンの「エル」)。わずかな変更(startIndex..<endIndex)で、これはこれまでに見つけた最良のソリューションであり、数行のコードで正確にこれを実行します。
ネフ

9

いくつかの便利な拡張:

extension String {
    func substring(from: Int, to: Int) -> String {
        let start = index(startIndex, offsetBy: from)
        let end = index(start, offsetBy: to - from)
        return String(self[start ..< end])
    }

    func substring(range: NSRange) -> String {
        return substring(from: range.lowerBound, to: range.upperBound)
    }
}

興味深いことに、私は同じことを考えていました。String(line ["http://" .endIndex ...])は非推奨のサブストリングよりも明確ですか?line.substring(from: "http://" .endIndex)は、驚くべき文字列処理という明確な目標を達成するまで、サブストリングを非推奨にするべきではありません。
possen 2017年

7

uppercasedFirstCharacterSwift3およびSwift4 のコンビニエンスプロパティの例。

プロパティuppercasedFirstCharacterNewは、Swift4で文字列スライス添え字を使用する方法を示します。

extension String {

   public var uppercasedFirstCharacterOld: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = substring(to: splitIndex).uppercased()
         let sentence = substring(from: splitIndex)
         return firstCharacter + sentence
      } else {
         return self
      }
   }

   public var uppercasedFirstCharacterNew: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = self[..<splitIndex].uppercased()
         let sentence = self[splitIndex...]
         return firstCharacter + sentence
      } else {
         return self
      }
   }
}

let lorem = "lorem".uppercasedFirstCharacterOld
print(lorem) // Prints "Lorem"

let ipsum = "ipsum".uppercasedFirstCharacterNew
print(ipsum) // Prints "Ipsum"

1
部分文字列を意味する場合(範囲:付き)-> self [範囲]
Arsen Vartbaronov '18

6

以下のように、クラスStringへの拡張を使用して、カスタムsubStringメソッドを作成できます。

extension String {
    func subString(startIndex: Int, endIndex: Int) -> String {
        let end = (endIndex - self.count) + 1
        let indexStartOfText = self.index(self.startIndex, offsetBy: startIndex)
        let indexEndOfText = self.index(self.endIndex, offsetBy: end)
        let substring = self[indexStartOfText..<indexEndOfText]
        return String(substring)
    }
}

これがendIndexを取り込む場合は、範囲外も処理できる必要があります。
ジェイ

5

Swift 4を使用して文字列からSubString(プレフィックスとサフィックス)を作成する:

let str : String = "ilike"
for i in 0...str.count {
    let index = str.index(str.startIndex, offsetBy: i) // String.Index
    let prefix = str[..<index] // String.SubSequence
    let suffix = str[index...] // String.SubSequence
    print("prefix \(prefix), suffix : \(suffix)")
}

出力

prefix , suffix : ilike
prefix i, suffix : like
prefix il, suffix : ike
prefix ili, suffix : ke
prefix ilik, suffix : e
prefix ilike, suffix : 

2つのインデックスの間に部分文字列を生成する場合は、次を使用します。

let substring1 = string[startIndex...endIndex] // including endIndex
let subString2 = string[startIndex..<endIndex] // excluding endIndex

str [.. <index>]の代わりにprefix = str [... <index>]を使用すると、単一のドットが欠落します。
AbuTaareq 2018

@AbuTaareq、あなたが話しているのはどれ?prefix = str [.. <index]とすると、完璧です。(プレフィックス文字列)。より多くのコンテキストを得るために遊び場で試してください。
Ashis Laha 2018年

4

'String:subString:'を置き換えるための文字列拡張を作成しました

extension String {

    func sliceByCharacter(from: Character, to: Character) -> String? {
        let fromIndex = self.index(self.index(of: from)!, offsetBy: 1)
        let toIndex = self.index(self.index(of: to)!, offsetBy: -1)
        return String(self[fromIndex...toIndex])
    }

    func sliceByString(from:String, to:String) -> String? {
        //From - startIndex
        var range = self.range(of: from)
        let subString = String(self[range!.upperBound...])

        //To - endIndex
        range = subString.range(of: to)
        return String(subString[..<range!.lowerBound])
    }

}

使用法 : "Date(1511508780012+0530)".sliceByString(from: "(", to: "+")

結果の例:「1511508780012」

PS:オプションはアンラップを強制されます。必要に応じてタイプセーフチェックを追加してください。


注意:オプションはアンラップを強制されます。必要に応じてタイプセーフチェックを追加してください。
by Jeevan 2018年

3

プログラミング時には、プレーンなA-Za-zと0-9だけの文字列がよくあります。難しいインデックス操作は必要ありません。この拡張機能は、単純な古いleft / mid / right関数に基づいています。

extension String {

    // LEFT
    // Returns the specified number of chars from the left of the string
    // let str = "Hello"
    // print(str.left(3))         // Hel
    func left(_ to: Int) -> String {
        return "\(self[..<self.index(startIndex, offsetBy: to)])"
    }

    // RIGHT
    // Returns the specified number of chars from the right of the string
    // let str = "Hello"
    // print(str.left(3))         // llo
    func right(_ from: Int) -> String {
        return "\(self[self.index(startIndex, offsetBy: self.length-from)...])"
    }

    // MID
    // Returns the specified number of chars from the startpoint of the string
    // let str = "Hello"
    // print(str.left(2,amount: 2))         // ll
    func mid(_ from: Int, amount: Int) -> String {
        let x = "\(self[self.index(startIndex, offsetBy: from)...])"
        return x.left(amount)
    }
}

いい案!!ただし、Swiftの機能を抽象化する必要があることは残念です。彼らは私たち全員に生産性ではなく構造に集中してほしいと思っていると思います。とにかく、私はあなたの細かいコードにいくつかのマイナーな更新を行いました:pastebin.com/ManWmNnW
Fredrik Johansson

2

このメソッドを使用すると、特定の範囲の文字列を取得できます。開始インデックスを渡し、その後に必要な文字数を渡す必要があります。

extension String{
    func substring(fromIndex : Int,count : Int) -> String{
        let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
        let endIndex = self.index(self.startIndex, offsetBy: fromIndex + count)
        let range = startIndex..<endIndex
        return String(self[range])
    }
}

2

これは私の解決策であり、警告もエラーもありませんが、完璧です

let redStr: String = String(trimmStr[String.Index.init(encodedOffset: 0)..<String.Index.init(encodedOffset: 2)])
let greenStr: String = String(trimmStr[String.Index.init(encodedOffset: 3)..<String.Index.init(encodedOffset: 4)])
let blueStr: String = String(trimmStr[String.Index.init(encodedOffset: 5)..<String.Index.init(encodedOffset: 6)])

の使用encodedOffset有害と見なされ非推奨となります。
Martin R

1

これがもう少し役立つことを願っています:-

var string = "123456789"

特定のインデックスの後に部分文字列が必要な場合。

var indexStart  =  string.index(after: string.startIndex )// you can use any index in place of startIndex
var strIndexStart   = String (string[indexStart...])//23456789

最後の文字列を削除した後に部分文字列が必要な場合。

var indexEnd  =  string.index(before: string.endIndex)
var strIndexEnd   = String (string[..<indexEnd])//12345678

次のコードでインデックスを作成することもできます:-

var  indexWithOffset =  string.index(string.startIndex, offsetBy: 4)

0

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

extension String {
    func getSubString(_ char: Character) -> String {
        var subString = ""
        for eachChar in self {
            if eachChar == char {
                return subString
            } else {
                subString += String(eachChar)
            }
        }
        return subString
    }
}


let str: String = "Hello, playground"
print(str.getSubString(","))

0
var str = "Hello, playground"
let indexcut = str.firstIndex(of: ",")
print(String(str[..<indexcut!]))
print(String(str[indexcut!...]))

この方法で試すことができ、適切な結果が得られます。

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