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 =“ - ”
我只有几周的编程时间。任何人都可以帮忙吗?有没有更好的方法来做我想做的事情?非常感谢你。
答案 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: "")
这将取你的字符串并删除所有字母字符,只留下数字。然后,您可以根据需要将字符串转换为整数!