Calculating risk levels

Let's consider following function that return some risk levels enum type:

func calculateRiskLevel()-> ResultFirstLevels
{
let result = self.result
if result < 1
{
return .Level1
}
else if result >= 1 && result < 5
{
return .Level2
}
else if result >= 5 && result < 10
{

return .Level3
}
else
{
return .Level4
}

}


I'm pretty sure there is a more clever way to achieve that.

I was thinking about a dictionary with some key-value coding, but how can I incorporate conditional statements within keys?

Could you suggest some "more professional" way to deal with such parsing with conditional statements?

If you need risk level to be an enum (which sounds like good idea anyway), it would be nice to tightly couple the meaning of, say, Risk.Level2 with the range of raw values it represents, such as 1..<5. In other words, the enum itself should define all the applicable ranges. Depending on your specific needs, one of the following two approaches may be along the lines of what you're looking for:

enum Risk {

case Level1, Level2, Level3, Level4

var range: Range<Int> {
switch self {
case Level1: return 0..<1
case Level2: return 1..<5
case Level3: return 5..<10
case Level4: return 10..<Int.max
}
}

init(_ risk: Int) {
switch risk {
case Level2.range: self = Level2
case Level3.range: self = Level3
case Level4.range: self = Level4
default: self = Level1
}
}
}

Risk(5) //--> Risk.Level3


Or:

enum Risk: Int {

case Level1 = 0
case Level2 = 1
case Level3 = 5
case Level4 = 10

var range: Range<Int> {
switch self {
case Level1: return Level1.rawValue..<Level2.rawValue
case Level2: return Level2.rawValue..<Level3.rawValue
case Level3: return Level3.rawValue..<Level4.rawValue
case Level4: return Level4.rawValue..<Int.max
}
}

init(_ risk: Int) {
switch risk {
case Level2.range: self = Level2
case Level3.range: self = Level3
case Level4.range: self = Level4
default: self = Level1
}
}
}

Risk(5) //--> Risk.Level3


This would all be much nicer if we could have enum Risk: Range<Int>. Unfortunately, Range<Int> cannot be expressed as a literal, so cases could not be assigned rawValues...

I'd rather use the switch statement.

PoC:

Example - Classic:

if num == 0 {
return 12
} else if num == 1 {
return 24
} else {
return 36
}


Example - With switch statement:

switch(num) {
case 0: return 12
case 1: return 24
case 2: fallthrough
default: return 36
}


2 case is handled by the default case, using the fallthrough keyword. Now you are able to apply this method to your code.

Following the example, an alternative way to achieving the same, taking into account that the possible values are consecutive and starting from 0, is using an array:

let val = [12, 24, 36]
return val[num]


If the function is a class/struct method, the val array can be defined as a static (class) property outside the function, just to avoid instantiating it for each function call. Note that this solution generates a runtime exception if the num value is not in the [0, 2] range.

I suggest you to apply the method by using the switch statement.

• well, how to apply ranges instead of values to switch statement? how to make this if result >= 5 && result < 10 a case?
– DCDC
Commented Nov 20, 2015 at 22:55
• @DCDC something like case 0..<10: which means, in this case, "between 0 and 10" Commented Nov 20, 2015 at 23:07
• alright :) So switch would be certainly better option here :) any ideas with dictionaries?
– DCDC
Commented Nov 20, 2015 at 23:10
• @DCDC To have the same code executed for two case, you could do case "first", "second": or use fallthrough keyword. Commented Nov 20, 2015 at 23:13
• Why would you use dictionaries? Commented Nov 20, 2015 at 23:21