Ios 将由4个数字组成的字符串解析为CGRect

Ios 将由4个数字组成的字符串解析为CGRect,ios,string,swift,Ios,String,Swift,我有这个字符串(325140739979)。我想对它进行解析,分别取四个数字 此字符串表示一个CGRect。我想取第一个数字为x第二个数字为y第三个数字为width,最后一个数字为height 实现这一点的最佳方法是什么?首先,我们可以去掉括号 let myString = "(325, 140, 739, 979)" let myReplacementString = String(map(myString.generate()) { $0 == "(" || $0 == ")" ? "-

我有这个字符串
(325140739979)
。我想对它进行解析,分别取四个数字

此字符串表示一个
CGRect
。我想取第一个数字为
x
第二个数字为
y
第三个数字为
width
,最后一个数字为
height


实现这一点的最佳方法是什么?

首先,我们可以去掉括号

let myString = "(325, 140, 739, 979)"
let myReplacementString = String(map(myString.generate()) {
  $0 == "(" || $0 == ")" ? "-" : $0
})
您还可以使用子字符串,这似乎没有更好的效果

然后我们可以将字符串拆分为数组

var myArray = myReplacementString.componentsSeparatedByString(", ")
然后使用循环将字符串强制转换为int

for item in myArray {
    item.toInt()
}

或者只需使用myArray[i].toInt()将它们直接提供给构造函数等。

以下是我针对您的案例的解决方案:

func parse(str : String) -> [Int] {
        var firstStepStr = str.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "()"))  //remove ( and )
        var secondStepArray =  firstStepStr.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: ", ")).filter{$0 != ""}  //separated by , and ignore ""
        return  secondStepArray.map{$0.toInt() ?? 0}  //convert to [Int], if cannot convert to Int, return 0
    }

let cgrectString = "(325, 140, 739, 979)"
let intArray = parse(cgrectString)

这将得到一个包含四个CGFloat值的数组:

func stringToCGFloatArray(string: String) -> [CGFloat] {
    return string.componentsSeparatedByCharactersInSet(
        NSCharacterSet(charactersInString: "(), ")).reduce([CGFloat]()) {
        if let x = $1.toInt() {
            return $0 + [CGFloat(x)]
        } else {
            return $0
        }
    }
}
然后可以将其转换为可选元组,该元组可以直接提供给
CGMakeRect

func arrayToRectParameters(array: [CGFloat]) -> (CGFloat, CGFloat, CGFloat, CGFloat)? {
    switch array.count {
    case 4:
        return (array[0], array[1], array[2], array[3])
    default:
        return nil
    }
}
extension CGRect {
    init?(string: String) {
        // note, since CGRect also has a contains method, need to specify Swift.contains
        let nums = split(string) { Swift.contains("(), ", $0) }.map { $0.toInt() }

        if nums.count == 4,
            let x = nums[0], y = nums[1],
                w = nums[2], h = nums[3]
        {
            self = CGRect(x: x, y: y, width: w, height: h)
        }
        else {
            return nil
        }
    }
}

let rectangles = [
    "(325, -140, 739, 979)", // valid
    "(1,2,3,asdadaf)",       // invalid (non-integer)
    "1,2,3,4,",              // valid
    "(1,2,3,4,5)",           // invalid (wrong count)
]


// returns an array of 2 valid CGRect and 2 nil
let cgrects = rectangles.map { CGRect(string: $0) }
现在您可以创建一个CGRect,如下所示:

let str = "(325, 140, 739, 979)"

if let rectParameters = arrayToRectParameters(stringToCGFloatArray(str)) {
    let myCGRect = CGRectMake(rectParameters)
    println(myCGRect)     // prints (325.0,140.0,739.0,979.0)
}
let str = "(325, 140, 739, 979)"
let nums = split(str) { contains("(), ", $0) }.map { $0.toInt() }

给定字符串,可以将数字作为可选的
Int
数组获取,如下所示:

let str = "(325, 140, 739, 979)"

if let rectParameters = arrayToRectParameters(stringToCGFloatArray(str)) {
    let myCGRect = CGRectMake(rectParameters)
    println(myCGRect)     // prints (325.0,140.0,739.0,979.0)
}
let str = "(325, 140, 739, 979)"
let nums = split(str) { contains("(), ", $0) }.map { $0.toInt() }
split
将删除传递给
contains
的字符串中的任何字符。现在,您有了一个选项数组,可以检查其内容是否正确:

let rect: CGRect
if nums.count == 4,
   let x = nums[0], y = nums[1],
       w = nums[2], h = nums[3]
{
    rect = CGRect(x: x, y: y, width: w, height: h)
}
else {
    // report an error, or default the values if you prefer
    fatalError("Malformed input string")
}
输入字符串中的任何无关字符都将导致其中一个整数的
nil
,或者数组中的计数错误,因此这对于任何垃圾输入都是安全的

为了方便起见,您可以将所有这些都放在
CGRect
的可失败初始值设定项中:

func arrayToRectParameters(array: [CGFloat]) -> (CGFloat, CGFloat, CGFloat, CGFloat)? {
    switch array.count {
    case 4:
        return (array[0], array[1], array[2], array[3])
    default:
        return nil
    }
}
extension CGRect {
    init?(string: String) {
        // note, since CGRect also has a contains method, need to specify Swift.contains
        let nums = split(string) { Swift.contains("(), ", $0) }.map { $0.toInt() }

        if nums.count == 4,
            let x = nums[0], y = nums[1],
                w = nums[2], h = nums[3]
        {
            self = CGRect(x: x, y: y, width: w, height: h)
        }
        else {
            return nil
        }
    }
}

let rectangles = [
    "(325, -140, 739, 979)", // valid
    "(1,2,3,asdadaf)",       // invalid (non-integer)
    "1,2,3,4,",              // valid
    "(1,2,3,4,5)",           // invalid (wrong count)
]


// returns an array of 2 valid CGRect and 2 nil
let cgrects = rectangles.map { CGRect(string: $0) }
很明显,如果你想在你愿意转换的输入类型上或多或少的宽容,这里有很多可以调整的地方