数字以外のすべての文字を文字列からすばやく削除します


84

数値である必要があるが、空白またはその他の英数字以外の文字が含まれている可能性がある不明なデータを解析する必要があります。

Swiftでこれを行う新しい方法はありますか?私がオンラインで見つけることができるのは、物事を行う古いCの方法のようです。

私が見てstringByTrimmingCharactersInSetいるのは、入力の文字列の先頭または末尾に空白/特殊文字のみが含まれると確信しているためです。これに使用できる組み込みの文字セットはありますか?または、自分で作成する必要がありますか?

stringFromCharactersInSet()有効な文字だけを指定して保持できるようなものがあることを望んでいました

回答:


183

stringFromCharactersInSet()のように、保持する有効な文字のみを指定できるものがあることを期待していました。

文字セットtrimmingCharactersとともに使用してinverted、文字列の先頭または末尾から文字を削除できます。Swift 3以降の場合:

let result = string.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789.").inverted)

または、文字列内の任意の場所(開始または終了だけでなく)を削除する場合filtercharacters、たとえばSwift4.2.1で次のように実行できます。

let result = string.filter("0123456789.".contains)

または、文字列内の任意の場所からCharacterSetから文字を削除する場合は、次を使用します。

let result = String(string.unicodeScalars.filter(CharacterSet.whitespaces.inverted.contains))

または、特定の形式(たとえば####.##)の有効な文字列のみを照合する場合は、正規表現を使用できます。例えば:

if let range = string.range(of: #"\d+(\.\d*)?"#, options: .regularExpression) {
    let result = string[range] // or `String(string[range])` if you need `String`
}

これらの異なるアプローチの動作はわずかに異なるため、何をしようとしているかによって異なります。10進数、または整数のみが必要な場合は、小数点を含めるか除外します。これを達成する方法はたくさんあります。


古いSwift2構文については、この回答の以前のリビジョンを参照してください。


invertedSwift 3の例の文字セットで行う必要がある理由を説明できますか?
Andy Ibanez

4
@AndyIbanez「ABC」が保持したい文字である場合は、「ABC」以外のすべてをトリミングすると言っているようなものです。
スコットマッケンジー

1
Swiftでは、4.2.1let result = String(string.characters.filter { "01234567890.".characters.contains($0) })は次のように短縮できますlet result = string.filter("01234567890.".contains)
LeoDabus19年

41
let result = string.stringByReplacingOccurrencesOfString("[^0-9]", withString: "", options: NSStringCompareOptions.RegularExpressionSearch, range:nil).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())

スウィフト3

let result = string.replacingOccurrences( of:"[^0-9]", with: "", options: .regularExpression)

あなたはこの答えに賛成することができます


3
ありがとう!Swift3のすべての変更を取得した後、次のようになりました:myStr.replacingOccurrences(of: "[^ 0-9]"、with: ""、options:.regularExpression)
bobwki 2017年

29

私は拡張機能が好きなので、このソリューションを好みます。少しすっきりしているようです。ここで再現されたソリューション:

extension String {
    var digits: String {
        return components(separatedBy: CharacterSet.decimalDigits.inverted)
            .joined()
    }
}

ストリップ小数に思える
markturnip

18

Swift 4

文字列から英数字セットのみ取得する適切な方法を見つけました。例えば:-

func getAlphaNumericValue() {

    var yourString  = "123456789!@#$%^&*()AnyThingYouWant"

    let unsafeChars = CharacterSet.alphanumerics.inverted  // Remove the .inverted to get the opposite result.  

    let cleanChars  = yourString.components(separatedBy: unsafeChars).joined(separator: "")


    print(cleanChars)  // 123456789AnyThingYouWant

}

17

範囲のパターンマッチング演算子を使用して文字列のUnicodeScalarViewをフィルタリングし、0から9までのUnicodeScalar ClosedRangeを渡して、結果のUnicodeScalarViewで新しい文字列を初期化できます。

extension String {
    private static var digits = UnicodeScalar("0")..."9"
    var digits: String {
        return String(unicodeScalars.filter(String.digits.contains))
    }
}

"abc12345".digits   // "12345"

編集/更新:

Swift 4.2

extension RangeReplaceableCollection where Self: StringProtocol {
    var digits: Self {
        return filter(("0"..."9").contains)
    }
}

または突然変異法として

extension RangeReplaceableCollection where Self: StringProtocol {
    mutating func removeAllNonNumeric() {
        removeAll { !("0"..."9" ~= $0) }
    }
}

Swift5.2•Xcode11.4以降

Swift5では、次のような新しいCharacterプロパティを使用できますisWholeNumber

extension RangeReplaceableCollection where Self: StringProtocol {
    var digits: Self { filter(\.isWholeNumber) }
}

extension RangeReplaceableCollection where Self: StringProtocol {
    mutating func removeAllNonNumeric() {
        removeAll { !$0.isWholeNumber }
    }
}

ピリオドも許可するために、Characterを拡張して、計算されたプロパティを作成できます。

extension Character {
    var isDecimalOrPeriod: Bool { "0"..."9" ~= self || self == "." }
}

extension RangeReplaceableCollection where Self: StringProtocol {
    var digitsAndPeriods: Self { filter(\.isDecimalOrPeriod) }
}

遊び場のテスト:

"abc12345".digits   // "12345"

var str = "123abc0"
str.removeAllNonNumeric()
print(str) //"1230"

"Testing0123456789.".digitsAndPeriods // "0123456789."

Swift 5の優れたソリューション!どうすれば「。」を離れることができますか。または文字列内の「、」、文字列をダブルに変換できるようにしますか?
ハンスボンドカ

1
@HansBondokaありがとうfilter { $0.isNumber || $0 == "." }。このようにしてみてください。
レオダバス

11

filter関数とを使用したソリューションrangeOfCharacterFromSet

let string = "sld [f]34é7*˜µ"

let alphaNumericCharacterSet = NSCharacterSet.alphanumericCharacterSet()
let filteredCharacters = string.characters.filter {
  return  String($0).rangeOfCharacterFromSet(alphaNumericCharacterSet) != nil
}
let filteredString = String(filteredCharacters) // -> sldf34é7µ

数字のみをフィルタリングするには、

let string = "sld [f]34é7*˜µ"

let numericSet = "0123456789"
let filteredCharacters = string.characters.filter {
  return numericSet.containsString(String($0))
}
let filteredString = String(filteredCharacters) // -> 347

または

let numericSet : [Character] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
let filteredCharacters = string.characters.filter {
  return numericSet.contains($0)
}
let filteredString = String(filteredCharacters) // -> 347

アルファ値は必要ありませんが、必要ありません
Dan

具体的にお願いします。見出しにはnon-alphanumeric;-)数字の答えを編集しました。
vadian 2016

8

スウィフト4

しかし、拡張機能やcomponentsSeparatedByCharactersInSetがないと、同様に読み取れません。

let allowedCharSet = NSCharacterSet.letters.union(.whitespaces)
let filteredText = String(sourceText.unicodeScalars.filter(allowedCharSet.contains))

4

Swift 3、数値を除くすべてをフィルタリング

let myString = "dasdf3453453fsdf23455sf.2234"
let result = String(myString.characters.filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil })
print(result)

3

Swift 4.2

let numericString = string.filter { (char) -> Bool in
    return char.isNumber
}

2

あなたはこのようなことをすることができます...

let string = "[,myString1. \"" // string : [,myString1. " 
let characterSet = NSCharacterSet(charactersInString: "[,. \"")
let finalString = (string.componentsSeparatedByCharactersInSet(characterSet) as NSArray).componentsJoinedByString("") 
print(finalString)   
//finalString will be "myString1"

文字列に含まれる可能性のある文字について完全にはわかりません。最後に数値のみが必要です。これは私が望まないすべての文字をリストする必要があるでしょう..可能性のある文字がたくさんあります
ダン

2

Robの最初の解決策の問題stringByTrimmingCharactersInSetは、Appleのドキュメントに記載されているように、文字列全体ではなく、文字列の末尾のみをフィルタリングすることです。

指定された文字セットに含まれるレシーバー文字の両端から削除された新しい文字列を返します。

代わりに、を使用componentsSeparatedByCharactersInSetして、最初に文字セットのすべての非出現を配列に分離し、次にそれらを空の文字列区切り文字で結合します。

"$$1234%^56()78*9££".componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "0123456789").invertedSet)).joinWithSeparator("")

どちらが戻る 123456789


使用する必要はありませんNSCharacterSet。しかし、あなたの答えは最高です。ここでは、一般的なバージョンがあります:extension String { func removingCharactersNot(in charSet: CharacterSet) -> String { return self.components(separatedBy: charSet.inverted).joined(separator: "") } }
xaphod

2

スウィフト3

extension String {
    var keepNumericsOnly: String {
        return self.components(separatedBy: CharacterSet(charactersIn: "0123456789").inverted).joined(separator: "")
    }
}

2
let string = "+1*(234) fds567@-8/90-"
let onlyNumbers = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()

print(onlyNumbers) // "1234567890"

または

extension String {

  func removeNonNumeric() -> String {
    return self.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
  }
}

let onlyNumbers = "+1*(234) fds567@-8/90-".removeNonNumeric() 
print(onlyNumbers)// "1234567890"

1

Swift4.0バージョン

extension String {
    var numbers: String {
        return String(describing: filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil })
    }
}

1

スウィフト4

String.swift

import Foundation

extension String {

    func removeCharacters(from forbiddenChars: CharacterSet) -> String {
        let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
        return String(String.UnicodeScalarView(passed))
    }

    func removeCharacters(from: String) -> String {
        return removeCharacters(from: CharacterSet(charactersIn: from))
    }
}

ViewController.swift

let character = "1Vi234s56a78l9"
        let alphaNumericSet = character.removeCharacters(from: CharacterSet.decimalDigits.inverted)
        print(alphaNumericSet) // will print: 123456789

        let alphaNumericCharacterSet = character.removeCharacters(from: "0123456789")
        print("no digits",alphaNumericCharacterSet) // will print: Vishal

新しいUnicodeScalarViewを初期化することは無意味です。フィルタの結果は、すでにUnicodeScalarViewです。return String(passed)
Leo Dabus 2017年

1

Swift 4.2

let digitChars  = yourString.components(separatedBy:
        CharacterSet.decimalDigits.inverted).joined(separator: "")

0

Swift3バージョン

extension String
{
    func trimmingCharactersNot(in charSet: CharacterSet) -> String
    {
        var s:String = ""
        for unicodeScalar in self.unicodeScalars
        {
            if charSet.contains(unicodeScalar)
            {
                s.append(String(unicodeScalar))
            }
        }
        return s
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.