Arrays 从包含某些(双)字符的字符串创建字符串数组
我有一串单词和数学/编程使用的符号。例如,类似这样的内容:Arrays 从包含某些(双)字符的字符串创建字符串数组,arrays,swift,string,Arrays,Swift,String,我有一串单词和数学/编程使用的符号。例如,类似这样的内容: var source = "a + b + 3 == c" let symbols = ["+", "-", "==", "!="] var results: [Substring] = [] for symbol in symbols { var startIndex = source.startIndex var
var source = "a + b + 3 == c"
let symbols = ["+", "-", "==", "!="]
var results: [Substring] = []
for symbol in symbols {
var startIndex = source.startIndex
var ranges: [Range<String.Index>] = []
while startIndex < source.endIndex,
let range = source[startIndex...].range(of: symbol) {
ranges.append(range)
results.append(source[range])
startIndex = source.index(after: range.upperBound)
}
for range in ranges.reversed() {
source.removeSubrange(range)
}
}
print(results)
let source=“a+b+3==c”
(注意:不能依赖空格)
我还有一个字符串数组,需要从源字符串中筛选出来:
让符号=[“+”、“-”、“==”、“!=”]
现在,我需要创建一个匹配项的数组(带有重复项)。在这种情况下,这将是[“+”,“+”,“==”]
根据我的尝试,==
是两个字符,因此我无法执行以下操作:
let source=“a+b+3==c”
让符号=字符集(字符集:+-=≠") // 不是“==”和“!=”,而是“=”和“≠' 因为它是一个字符集
让操作=源
.map{String($0)}
.filter{symbols.contains中的字符(UnicodeScalar(char)!)}
打印(操作)
//输出:[“+”、“+”、“=”、“=”]
//需要:[“+”、“+”、“=”]
非常感谢您提供的任何帮助您需要的是将您的符号作为常规字符串进行威胁。迭代每个符号并在源代码中进行搜索。如果您找到一个范围,请将其附加到集合中,在该位置获取子字符串,然后从范围上限后的索引中再次搜索字符串。当您到达字符串搜索的结尾时对于该符号,请从源代码中删除子字符串。请尝试以下操作:
var source = "a + b + 3 == c"
let symbols = ["+", "-", "==", "!="]
var results: [Substring] = []
for symbol in symbols {
var startIndex = source.startIndex
var ranges: [Range<String.Index>] = []
while startIndex < source.endIndex,
let range = source[startIndex...].range(of: symbol) {
ranges.append(range)
results.append(source[range])
startIndex = source.index(after: range.upperBound)
}
for range in ranges.reversed() {
source.removeSubrange(range)
}
}
print(results)
var source=“a+b+3==c”
让符号=[“+”、“-”、“==”、“!=”]
变量结果:[子字符串]=[]
对于符号中的符号{
var startIndex=source.startIndex
变量范围:[范围]=[]
而startIndex
这会打印出来
[“+”、“+”、“=”]
这个问题是一个解析问题,就是将输入字符串转换成某种结构化数据。一个很好的方法是使用解析器组合器。虽然这个问题很复杂,但一旦设置好,示例“opStrings”函数就很容易理解,也很容易扩展
struct Parser<A> {
let run: (inout Substring) -> A?
static func always<A>(_ a: A) -> Parser<A> {
.init { _ in a }
}
static var never: Parser {
.init { _ in nil }
}
func map<B>(_ f: @escaping (A) -> B) -> Parser<B> {
Parser<B> { str -> B? in
self.run(&str).map(f)
}
}
func flatMap<B>(_ f: @escaping (A) -> Parser<B>) -> Parser<B> {
Parser<B> { str -> B? in
let original = str
let matchA = self.run(&str)
let parserB = matchA.map(f)
guard let matchB = parserB?.run(&str) else {
str = original
return nil
}
return matchB
}
}
func run(_ str: String) -> (match: A?, rest: Substring) {
var str = str[...]
let match = self.run(&str)
return (match, str)
}
}
func prefix(while p: @escaping (Character) -> Bool) -> Parser<Substring> {
Parser<Substring> { str in
let prefix = str.prefix(while: p)
str.removeFirst(prefix.count)
return prefix
}
}
func literalString(_ p: String) -> Parser<String?> {
Parser<String?> { str in
guard str.hasPrefix(p) else { return nil }
str.removeFirst(p.count)
return p
}
}
func literal(_ str: String) -> Parser<Void> {
literalString(str).map {
_ in ()
}
}
func oneOrMore<A>(_ predicate: @escaping (Character) -> Bool,
mapped f: @escaping (Substring) -> A) -> Parser<A> {
prefix(while: predicate)
.flatMap { $0.isEmpty ? .never : .always(f($0)) }
}
let oneOrMoreDecimals = oneOrMore((\.isNumber), mapped: Double.init)
.flatMap { d -> Parser<Double> in
guard let d = d else { return .never }
return .always(d)
}
func oneOf<A>(_ ps: [Parser<A>]) -> Parser<A> {
Parser<A> { str -> A? in
for p in ps {
if let match = p.run(&str) {
return match
}
}
return nil
}
}
let whitespace = oneOf([
literal(" "),
literal("\t"),
literal("\n")
])
let identifier = prefix(while: { ($0.isLetter && $0.isASCII) || $0.isNumber })
.flatMap { str -> Parser<String> in
guard let first = str.first else { return Parser.never }
return first.isNumber ? .never : .always(String(str))
}
let literalNumber = prefix(while: { $0.isNumber })
.flatMap { str -> Parser<Double> in
guard let value = Double(str) else { return Parser.never }
return .always(value)
}
func skip<T, U>(_ p: Parser<T>) -> Parser<U?> {
p.map { _ in nil }
}
struct Example {
enum Token {
case minus
case plus
case equal
case equalEqual
case notEqual
case identifier(String)
case number(Double)
}
enum Error: Swift.Error {
case unexpectedInput
}
let input: String
func run<T>(_ parsers: [Parser<T?>]) throws -> [T] {
var source = Substring(input)
var results: [T] = []
while let token = oneOf(parsers).run(&source) {
if let token = token {
results.append(token)
}
}
guard source.isEmpty else {
throw Error.unexpectedInput
}
return results
}
func tokenize() throws -> [Token] {
let tokenizers: [Parser<Token?>] = [
literal("-").map { .minus },
literal("+").map { .plus },
literal("==").map { .equalEqual },
literal("!=").map { .notEqual },
literal("=").map { .equal },
identifier.map { .identifier($0) },
oneOrMoreDecimals.map { .number($0) },
skip(whitespace)
]
return try run(tokenizers)
}
func opStrings() throws -> [String] {
try run([
literalString("-"),
literalString("+"),
literalString("=="),
literalString("!="),
literalString("="),
skip(identifier),
skip(oneOrMoreDecimals),
skip(whitespace),
] as [Parser<String?>])
}
}
do {
let example = Example(input: "a + b + 3 == c")
// let tokens = try example.tokenize()
print(try example.opStrings()) // ["+", "+", "=="]
}
catch {
print(error)
}
struct解析器{
让我们运行:(inout子字符串)->A?
静态func始终(a:a)->解析器{
.init{in a}
}
静态变量:解析器{
.init{in nil}
}
func映射(f:@escaping(A)->B)->解析器{
解析器{str->B?in
self.run(&str).map(f)
}
}
func平面映射(f:@escaping(A)->Parser)->Parser{
解析器{str->B?in
让原始=str
让matchA=self.run(&str)
让parserB=matchA.map(f)
guard let matchB=parserB?.run(&str)else{
str=原件
归零
}
返回匹配B
}
}
func run(str:String)->(匹配:A?,其余:子字符串){
var str=str[…]
让match=self.run(&str)
返回(匹配,str)
}
}
func前缀(而p:@escaping(Character)->Bool)->解析器{
解析器{str in
let prefix=str.prefix(while:p)
str.removeFirst(前缀.count)
返回前缀
}
}
func literalString(p:String)->解析器{
解析器{str in
guard str.hasPrefix(p)else{return nil}
str.removeFirst(p.count)
返回p
}
}
func literal(str:String)->解析器{
literalString(str).map{
_在()
}
}
func oneOrMore(u谓词:@escaping(Character)->Bool,
映射f:@escaping(子字符串)->A)->Parser{
前缀(while:predicate)
.flatMap{$0.isEmpty?.never:.always(f($0))}
}
设oneOrMoreDecimals=oneOrMore(\.isNumber),映射为:Double.init)
.flatMap{d->中的解析器
guard let d=d else{return.never}
返回。始终(d)
}
func oneOf(ps:[解析器])->Parser{
解析器{str->A?in
对于ps中的p{
如果let match=p.run(&str){
复赛
}
}
归零
}
}
让空白=其中一个([
文字(“”),
文字(“\t”),
文字(“\n”)
])
let identifier=前缀(while:{($0.isleter&&$0.isASCII)| |$0.isNumber})
.flatMap{str->中的解析器
guard let first=str.first-else{return Parser.never}
返回first.isNumber?.never:。始终(字符串(str))
}
让literalNumber=前缀(while:{$0.isNumber})
.flatMap{str->中的解析器
guard let value=Double(str)else{return Parser.never}
return.always(值)
}
func skip(p:Parser)->Parser{
p、 映射{uu}in nil}
}
结构示例{
枚举令牌{
减号
案例加号
大小写相等
格相等
案例说明
案例标识符(字符串)
案件编号(双)
}
枚举错误:Swift.Error{
未预料到的情况
}
让输入:字符串
func run(parsers:[Parser])抛出->[T]{
变量源=子字符串(输入)
var结果:[T]=[]
而let token=one/of(解析器)。运行(&source){
如果let token=token{
results.append(标记)
}
}
我没有别的了{
抛出错误
}
返回结果
}
func tokenize()抛出->[Token]{
让标记器:[解析器]=[
文字(“-”).map{.减号},
文字(“+”).map{.plus},
文字(“=”).map{.equalEqual},
文字(“!=”).map{.notEqual},
文字(“=”).map{.equal},
identifier.map{.identifier($0)},
oneOrMoreDecimals.map{.number($0)},
跳过(空白)