【问题标题】:Extract numbers from a String and save them to an array从字符串中提取数字并将它们保存到数组中
【发布时间】:2018-01-01 20:51:51
【问题描述】:

你好,我的朋友们,我需要你的帮助! :) 我是 swift 的绝对初学者,完全不知道自己在做什么。

我需要从我转换成字符串的 txt 文件中提取所有数字。 我想将所有数字保存到一个新的数组中,我还必须使用 CharacterView 来解决问题。

这是我到目前为止得到的。从txt文件读取没问题。

func readFile(){
    let path = Bundle.main.path(forResource: "paragraph", ofType: "txt")

    var fileContents : String? = nil
    do {
        fileContents = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)
    } catch _ as NSError {
        //ERROR HANDLING
    }
     print(fileContents)

}

这是文件:

§ 9 Lorem ipsum dolor (1) sat amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam。 (2) 床直径 voluptua。在 vero eos et accusam et justo duo 55 dolores 等等。 Stet clita kasd gubergren。 (3) 1 abore et dolore magna aliquyam erat,sed diam voluptua。在 vero eos et accusam et justo duo dolores et ea rebum。 Stet clita kasd.

感谢您的宝贵时间!

【问题讨论】:

  • 你的文件结构是什么?您打算如何存储这些数字?
  • 在您的paragraph9.txt 文件中包含内容示例
  • 谢谢你的回答。我在问题下方添加了txt文件
  • 显示你希望得到的输出。你只是想要[1,2,3]????还是[9,1,2,55,3,1]???什么?
  • 是的 [9,1,2,55,3,1]

标签: swift characterview


【解决方案1】:

详情

  • Xcode 10.2.1 (10E1001)、Swift 5

解决方案

import Foundation

extension String {
    func onlyNumbers() -> [NSNumber] {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        let charset = CharacterSet.init(charactersIn: " ,")
        return matches(for: "[+-]?([0-9]+([., ][0-9]*)*|[.][0-9]+)").compactMap { string in
            return formatter.number(from: string.trimmingCharacters(in: charset))
        }
    }

    // https://stackoverflow.com/a/54900097/4488252
    func matches(for regex: String) -> [String] {
        guard let regex = try? NSRegularExpression(pattern: regex, options: [.caseInsensitive]) else { return [] }
        let matches  = regex.matches(in: self, options: [], range: NSMakeRange(0, self.count))
        return matches.compactMap { match in
            guard let range = Range(match.range, in: self) else { return nil }
            return String(self[range])
        }
    }
}

用法

let text = "dasdxcw 12345678 eadwd 333.222 reqw 3 333 444.22, sfsa 44. qewqwdsaw qe aw, 0.123456678 and .23 asdasdas 32,322,222,444.8"
print("Original text: \(text)")
print("Only numbers: \(text.onlyNumbers())")

结果

//Original text: dasdxcw 12345678 eadwd 333.222 reqw 3 333 444.22, sfsa 44. qewqwdsaw qe aw, 0.123456678 and .23 asdasdas 32,322,222,444.8
//Only numbers: [12345678, 333.222, 3333444.22, 44, 0.123456678, 0.23, 32322222444.8]

【讨论】:

    【解决方案2】:

    这是一个简单的方法,不幸的是它不使用CharacterView,因为这会使它变得非常复杂:

    func readFile(){
      // Make sure getting the path and reading the file succeeds
      guard
        let path = Bundle.main.path(forResource: "paragraph", ofType: "txt"),
        let fileContents = try? String(contentsOfFile: path, encoding: String.Encoding.utf8) 
        else { return }
    
      // split string into substrings that only contain numbers
      let substrings = fileContents.components(separatedBy: CharacterSet.decimalDigits.inverted)
    
      // flatMap performs action on each substring
      // and only returns non-nil values,
      // thus returns [Int]
    
      let numbers = substrings.flatMap {
        // convert each substring into an Int?
        return Int($0)
      }
    
      print(numbers)
    }
    

    因为Int 的初始化程序采用String,所以不需要使用CharacterView。一旦文本中的数字从它们的非数字中分离出来,它们就可以直接从String 转换为Int。使用CharacterView 将是一个不必要的中间体。但是,您可以编写自己的 Int init?(String) 版本,它使用 CharacterView 来构建值。

    【讨论】:

    • 请注意,我不需要变量substrings,我可以跳过它并完成fileContents.components(separatedBy: CharacterSet.decimalDigits.inverted).flatMap { return Int($0) }。我将其分开以演示所涉及的步骤。
    猜你喜欢
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 2018-05-12
    • 2020-06-15
    • 1970-01-01
    • 2017-05-14
    相关资源
    最近更新 更多