Обычно это помогает разбить проблему на несколько функций. Здесь вам нужно сделать две вещи: обработать строку, извлечь номер и получить дополнительную информацию. Затем перебирайте массив строк, пока не найдете подходящую запись.
Сначала обработка струн. Учитывая строку, вы хотите вернуть либо пару (чтение и дополнительную информацию), либо «не найден». Всякий раз, когда вам нужно что-то возвращать или не найти, необязательный вариант является хорошим выбором. Итак, вы хотите функцию, которая принимает строку и возвращает дополнительный (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,]
посмотреть в использование регулярных выражений http://www.raywenderlich.com/86205/nsregularexpression-swift-tutorial – boidkan