2016-11-23 95 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) 
} 
相關問題