2015-05-17 1 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, я получаю данные AQI (индекс качества воздуха) с веб-сайта в виде NSString. AQI1 - AQI6 - это, по сути, данные AQI за каждый час (например, от 12 до 5 часов, я имею до AQI24 в фактическом коде). «#» означает, что данные еще недоступны. Целое число является AQI, и иногда может быть связана дополнительная информация, представленная «a»/«b» целыми числами, что означает «присутствующий монооксид углерода»/«присутствующий диоксид серы». То, что я пытаюсь сделать, это:Swift: Как получить последнее целое число из массива NSString?

1) Отображение последнего целое число от arrAQI (за исключением «#», а не отображать «а»/«B», которая является «88») на LabelAQI

2) Дисплей «Настоящий оксид углерода»/«Двуокись серы присутствует» на LabelExtraInfo, если есть «a»/«b» с последним целым числом из arrAQI, если нет, оставьте LabelExtraInfo.text = «-»

I 'всего лишь несколько недель в программировании. Может ли кто-нибудь помочь в этом? Есть ли лучший способ сделать то, что я хочу сделать? Огромное спасибо заранее.

+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

Должны объектыСоединенный массив - это конкретный тип массива (например, 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" 

я в первую очередь обратить массив и цикл через него для последнего без хэш записи символов. Затем я просматриваю строку сначала для числа и второй для букв a/b, используя поиск NSCharacterSet. Найдя, мы можем выйти из цикла, и все сделано.

Примечание: эта строка кода 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 
} 

Кстати, несколько других Swift советов: это, как правило, лучше использовать 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

может у объяснить, почему лучше использовать строку над NSString? – Wraithseeker

Смежные вопросы