Swift:如何从NSString数组中获取最后一个整数?

时间:2015-05-17 08:05:31

标签: ios arrays swift

var LabelAQI = "-"
var LabelExtraInfo = "-"

var arrAQI = [NSString]()

var AQI1:NSString = "55a"
var AQI2:NSString = "95a"
var AQI3:NSString = "66"
var AQI4:NSString = "25"
var AQI5:NSString = "88b"
var AQI6:NSString = "#"

arrAQI[0...5] = [AQI1, AQI2, AQI3, AQI4, AQI5, AQI6]

使用Swift,我以NSString的形式从网站获取AQI(空气质量指数)数据。 AQI1到AQI6基本上是每小时的AQI数据(例如,上午12点到凌晨5点,我在实际代码中达到了AQI24)。 “#”表示数据尚不可用。整数是AQI,并且有时可能存在由“a”/“b”表示的相关额外信息,其中整数表示“存在一氧化碳”/“存在二氧化硫”。我要做的是:

1)在LabelAQI上显示arrAQI的最后一个整数(不包括“#”,而不显示“a”/“b”,即“88”)

2)如果存在来自arrAQI的最后一个整数的“a”/“b”,则在LabelExtraInfo上显示“存在一氧化碳”/“存在二氧化硫”,如果没有,请保留LabelExtraInfo.text =“ - ”

我只有几周的编程时间。任何人都可以帮忙吗?有没有更好的方法来做我想做的事情?非常感谢你。

4 个答案:

答案 0 :(得分:2)

通常有助于将问题分解为多个功能。在这里,您需要做两件事 - 处理字符串,提取数字和可能的额外信息。然后,遍历字符串数组,直到找到合适的条目。

首先进行字符串处理。给定一个字符串,您想要返回一对(读数和额外信息)或“未找到”。无论何时需要返回或未找到的东西,选项都是不错的选择。所以你想要一个带字符串的函数并返回一个可选的(Int,String)对:

func extractData(input: String) -> (Int,String)?

但是你可以更进一步,定义一个枚举来表示额外信息的不同部分:

enum AirQualityInfo {
    case CarbonMonoxide,
         SulphurDioxide,
         NoInfo
}

func extractData(input: String) -> (Int,AirQualityInfo)?

这样,所有讨厌的字符串处理都包含在extractData

在该函数中,您要检查已知的尾随字符,然后将其删除,如果剩下的是数字,则返回这两个值。但如果剩下的不是数字,请返回nil

func extractData(input: String) -> (Int,AirQualityInfo)? {

    let stripped: String
    let extraInfo: AirQualityInfo

    switch last(input) {
    case .Some("a"):
        stripped = dropLast(input)
        extraInfo = .CarbonMonoxide
    case .Some("b"):
        stripped = dropLast(input)
        extraInfo = .SulphurDioxide
    default:
        stripped = input
        extraInfo = .NoInfo
    }

    return stripped.toInt().map { ($0,extraInfo) }
}

正如其他人所建议的那样,您可以使用正则表达式,但我个人认为,鉴于您的数据解析需求非常具体,这是过度的。

一旦有了这个功能,就可以按相反的顺序循环遍历数组,使用函数检查每个值,直到找到有效值:

for idx in reverse(indices(arrAQI)) {
    if let (index, extraInfo) = extractData(arrAQI[idx]) {
        LabelAQI = toString(index)
        switch extraInfo {
        case .CarbonMonoxide:
            LabelExtraInfo = "Carbon Monoxide Present"
        case .SulphurDioxide:
            LabelExtraInfo = "SulphurDioxide Present"
        case .NoInfo:
            LabelExtraInfo = "-"
        }
        // stop going around the loop
        break
    }
}

您还可以将字符串的转换进一步分解:

extension AirQualityInfo {
    var displayString: String {
            switch self {
            case .CarbonMonoxide:
                return "Carbon Monoxide Present"
            case .SulphurDioxide:
                return "SulphurDioxide Present"
            case .NoInfo:
                return "-"
        }
    }
}

for idx in reverse(indices(arrAQI)) {
    if let (index, extraInfo) = extractData(arrAQI[idx]) {
       LabelAQI = toString(index)
       LabelExtraInfo = extraInfo.displayString
       break
    }
}

最后,如果您感觉超级冒险,您可以编写一个功能,一次性完成该查找和映射操作:

func findSome<C: CollectionType, T>
  (source: C, match: C.Generator.Element -> T?) 
  -> T? {
    for element in source {
        if let x = match(element) {
            return x
        }
    }
    return nil
}

if let (index, extraInfo) = findSome(reverse(arrAQI),extractData) {
    LabelAQI = toString(index)
    LabelExtraInfo = extraInfo.displayString
}

顺便提一下,其他一些Swift提示:除非你特别需要某个String(它不是{}},否则通常最好使用NSString而不是NSString看起来像这里);你不必在声明它们时命名类型 - 你可以写let str = "hello"而不是let str: String = "hello",这往往会使代码看起来更清晰,更容易阅读;并且最好使用let而不是var,除非您明确需要在代码中稍后更改(“mutate”)值...所以尽管如此,这里是您如何声明原始数组: / p>

let AQI1 = "55a"
let AQI2 = "95a"
let AQI3 = "66"
let AQI4 = "25"
let AQI5 = "88b"
let AQI6 = "#"

let arrAQI = [AQI1,AQI2,AQI3,AQI4,AQI5,AQI6,]

答案 1 :(得分:1)

有很多方法可以做到这一点,这里有一个使用NSScanner的建议:

var LabelAQI = "-"
var LabelExtraInfo = "-"

var arrAQI = [NSString]()

let AQI1:NSString = "55a", AQI2 = "95a", AQI3 = "66", AQI4 = "25", AQI5 = "88b", AQI6 = "#"    
arrAQI.extend([AQI1, AQI2, AQI3, AQI4, AQI5, AQI6])

for AQI in reverse(arrAQI) {
    if AQI != "#" {
        var str:NSString?

        let numberSet = NSCharacterSet.decimalDigitCharacterSet()    
        let letterSet = NSCharacterSet(charactersInString: "ab")

        let scanner = NSScanner(string: AQI as String)
        if scanner.scanCharactersFromSet(numberSet, intoString:&str) {
            LabelAQI = str as! String
            if scanner.scanCharactersFromSet(letterSet, intoString: &str) {
                switch str as! String {
                case "a":
                        LabelExtraInfo = "Carbon Monoxide present"

                case "b":
                        LabelExtraInfo = "Sulphur Dioxide present"

                default:
                    break
                }
            }
            break
        }

    }
}

LabelAQI // "88"
LabelExtraInfo // "Sulphur Dioxide present"

我首先反转数组并循环遍历最后一个非哈希符号条目。然后我首先扫描字符串中的数字,然后使用NSCharacterSet搜索扫描字母a / b。一旦找到,我们就可以摆脱循环,一切都完成了。

注意:这行代码arrAQI[0...5] = [AQI1, AQI2, AQI3, AQI4, AQI5, AQI6]无效,因此我将其替换为arrAQI.extend([AQI1, AQI2, AQI3, AQI4, AQI5, AQI6])

答案 2 :(得分:1)

这可以通过将字符串爆炸成对象数组来完成,然后检查每个对象:

var LabelAQI = "-"
var LabelExtraInfo = "-"

var stringFromServer = "55a 95a 66 25 88b #"

var objectsSeparated = stringFromServer.componentsSeparatedByString(" ")

for object in objectsSeparated
{
    if object.hasSuffix("a")
    {
        LabelAQI = object.substringToIndex(object.endIndex.predecessor())
        LabelExtraInfo = "Carbon Monoxide present"
    }
    else if object.hasSuffix("b")
    {
        LabelAQI = object.substringToIndex(object.endIndex.predecessor())
        LabelExtraInfo = "Sulphur Dioxide present"
    }
    else if object.hasSuffix("#")
    {
        LabelAQI = object.substringToIndex(object.endIndex.predecessor())
        LabelExtraInfo = "-"
    }
    else
    {
        LabelAQI = object
        LabelExtraInfo = "-"
    }
}

<强>更新

要找到最后一个对象,那就没有&#39;#&#39;后缀你可以使用以下代码:

var LabelAQI = "-"
var LabelExtraInfo = "-"

var stringFromServer = "55a 95a 66 25 88b #"

var objectsSeparated = stringFromServer.componentsSeparatedByString(" ")

var index = objectsSeparated.count

while 0 >= index
{
    var object = objectsSeparated[index]

    index--

    if object.hasSuffix("#")
    {
        //this object has '#' suffix -> skip it
        continue
    }
    else
    {
        //found non '#' object
        if object.hasSuffix("a")
        {
            LabelAQI = object.substringToIndex(object.endIndex.predecessor())
            LabelExtraInfo = "Carbon Monoxide present"
        }
        else if object.hasSuffix("b")
        {
            LabelAQI = object.substringToIndex(object.endIndex.predecessor())
            LabelExtraInfo = "Sulphur Dioxide present"
        }
        else
        {
            LabelAQI = object
            LabelExtraInfo = "-"
        }
        break
    }
}

答案 3 :(得分:0)

使用正则表达式,您可以轻松地从字符串中获取数字。你可能想要沿着这些方向做点什么:

let regex = NSRegularExpression(pattern: "[\a-z\s]", options: nil, error: nil)
let aq1value = regex?.stringByReplacingMatchesInString(arrAQI[0], options: nil, range: NSMakeRange(0, count(arrAQI[0])), withTemplate: "")

这将取你的字符串并删除所有字母字符,只留下数字。然后,您可以根据需要将字符串转换为整数!