2015-05-17 61 views
2
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”表示的相关额外信息,其中整数表示“存在一氧化碳”/“存在二氧化硫”。我试图做的是:Swift:如何从NSString数组中获取最后一个整数?

1)显示从arrAQI的最后一个整数(不包括 “#”,而不是LabelAQI

显示 “A”/ “B”,这是 “88”)

2)显示“一氧化碳本” /“二氧化硫本”上LabelExtraInfo如果有“一个” /“b”与来自arrAQI的最后一个整数,如果不是,离开LabelExtraInfo.text =“ - ”

我编程只有几个星期。任何人都可以帮忙吗?有没有更好的方式去做我想做的事情?提前谢谢你。

+0

考虑使用正则表达式 http://www.raywenderlich.com/86205/nsregularexpression-swift-tutorial – boidkan

回答

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 = "-" 
    } 
} 

UPDATE

为了找到最后一个对象,不具有“#”后缀可以使用下面的代码:

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 
    } 
} 
+0

谢谢!但如何只检查最后一个“非哈希”对象? –

+1

请参阅我的更新回答 –

+0

必须objectSeparated数组是特定类型的数组(例如String/NSString).hasSuffix才能正常工作? –

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: "") 

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

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

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

首先进行字符串处理。给定一个字符串,你想返回一对(阅读和额外的信息),或“未找到”。无论何时您需要返回或找不到,可选是一个不错的选择。所以,你想一个函数接受一个字符串,并返回一个可选(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 
} 

顺便说一句,其他一些斯威夫特提示:这是一般最好使用String而非NSString,除非你对某事物的具体需求是一个NSString(它看起来并不像这里);在声明它们时不需要命名这些类型 - 您可以编写let str = "hello"而不是let str: String = "hello",这往往会使代码看起来更简洁,更易于阅读;并且,最好在后面的代码使用let而不是var,除非你明确地需要改变(“变异”)值...所以鉴于这一切,这里是如何,你可以宣布你原来的数组:

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,] 
+0

u能解释为什么它更好地利用串过的NSString? – Wraithseeker

相关问题