2015-05-17 63 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

相關問題