2016-11-23 46 views
0

我是一个初学Swift和一般编程的初学者。我已经想出了一种基于不同年龄段编码具有不同平均值(M)和标准差(SD)值的z分数计算器的方法。但是,我将在我正在尝试构建的应用程序中重复使用该代码,并且我不想养成不良习惯,所以我希望得到一些关于是否会有更好/更多的反馈有效的方式来构造这个。我确信这只是看起来很明显,但基本上是用户输入的年龄,被分配到一个“年龄段”,他们在测验中的分数(这里没有编码)被转换为z分数,基于M和SD数据特定于他们的年龄组。任何意见或反馈将不胜感激。有没有一种更有效的方法来构建Swift中基于年龄组的z分数计算?

var age:(Int)! 

var ageClass:(String)! 

var TestScore: (Double)! 

age = 63 

TestScore = 28 

if (age <= 17) {ageClass = "ACInvalid"} 
else if (age <= 35) {ageClass = "AC1"} 
else if (age <= 50) {ageClass = "AC2"} 
else if (age <= 60) {ageClass = "AC3"} 
else if (age <= 70) {ageClass = "AC4"} 
else if (age <= 80) {ageClass = "AC5"} 
else if (age <= 109) {ageClass = "AC6"} 
else {ageClass = "ACInvalid"} 

//screen for ACInvalid 
if (ageClass == "ACInvalid") {"Invalid Age Range"} 
else { 

let TestScoreM: [String:Double] = ["AC1": 35.7, "AC2": 33.5, "AC3": 31.2, "AC4": 
29.4, "AC5": 26.1, "AC6": 22.1] 

let TestScoreSD: [String:Double] = ["AC1": 4.1, "AC2": 4.7, "AC3": 5.3, "AC4": 6.4, 
"AC5": 8.1, "AC6": 9.7] 

var TestScoreZ = (TestScore - TestScoreM[ageClass]!)/TestScoreSD[ageClass]! 
} 
+0

没有必要使用隐式展开自选您的变量(或在这种情况下,可变的变量)。只要说,例如'let age = 63','let testScore = 28.0','let age:String'(你可以推迟常量的初始化)。 – Hamish

回答

2

在你的情况,你可以尝试一个枚举,Swift有非常强大的枚举!

采取在我的代码,仔细一看,它比你的一样,但使用的强盛和斯威夫特的safeness:

enum AgeClass { 
    case AC1, AC2, AC3, AC4, AC5, AC6 

    static func from(age: Int) -> AgeClass? { 
    if (age <= 17) { 
     return nil 
    } 
    else if (age <= 35) { 
     return .AC1 
    } 
    else if (age <= 50) { 
     return .AC2 
    } 
    else if (age <= 60) { 
     return .AC3 
    } 
    else if (age <= 70) { 
     return .AC4 
    } 
    else if (age <= 80) { 
     return .AC5 
    } 
    else if (age <= 109) { 
     return .AC6 
    } 

    return nil 
    } 

    var mean: Double { 
    switch self { 
    case .AC1: 
     return 35.7 
    case .AC2: 
     return 33.5 
    case .AC3: 
     return 31.2 
    case .AC4: 
     return 29.4 
    case .AC5: 
     return 26.1 
    case .AC6: 
     return 22.1 
    } 
    } 

    var standardDeviation: Double { 
    switch self { 
    case .AC1: 
     return 4.1 
    case .AC2: 
     return 4.7 
    case .AC3: 
     return 5.3 
    case .AC4: 
     return 6.4 
    case .AC5: 
     return 8.1 
    case .AC6: 
     return 9.7 
    } 
    } 
} 

let age = 63 
guard let ageClass = AgeClass.from(age: age) else { 
    fatalError("AgeClass is invalid") 
} 

let testScore: Double = 28 
let testScoreZ = testScore - ageClass.mean/ageClass.standardDeviation 
+1

处理无效输入的更好方法是简单地使'from(age:Int)'返回一个可选项,而不是有一个特殊的“无效”的情况。这样你就可以省去默认的0返回,并且调用者在展开时选择他们想要处理无效输入的方式。 – Hamish

+0

我会根据该编辑!好想法 – Dean

0

有很多种方法来此。我最喜欢的选择是定义2个类别:一个定义年龄类别,另一个定义参考数据。这样,您就可以从文件中加载ReferenceData或核心数据而不是硬编码到他们的程序:

enum AgeClass : Int { 
    case ac1 
    case ac2 
    case ac3 
    case ac4 
    case ac5 
    case ac6 
    case invalid 

    init(age: Int) { 
     switch age { 
     case 18...35: 
      self = .ac1 
     case 36...50: 
      self = .ac2 
     case 51...60: 
      self = .ac3 
     case 61...70: 
      self = .ac4 
     case 71...80: 
      self = .ac5 
     case 81...109: 
      self = .ac6 
     default: 
      self = .invalid 
     } 
    } 
} 

struct ReferenceData { 
    static var mean: [AgeClass : Double] = [ 
     .ac1: 35.7, 
     .ac2: 33.5, 
     .ac3: 31.2, 
     .ac4: 29.4, 
     .ac5: 26.1, 
     .ac6: 22.1 
    ] 
    static var standardDeviation: [AgeClass : Double] = [ 
     .ac1: 4.1, 
     .ac2: 4.7, 
     .ac3: 5.3, 
     .ac4: 6.4, 
     .ac5: 8.1, 
     .ac6: 9.7 
    ] 
} 

let age = 63 
let testScore = 28.0 

// Example 
let ageClass = AgeClass(age: age) 
if let mean = ReferenceData.mean[ageClass], 
    let stddev = ReferenceData.standardDeviation[ageClass] { 
    let testScoreZ = (testScore - mean)/stddev 
    print(testScoreZ) 
} 
相关问题