在 Go 中用数字范围编写多个嵌套的 if-else 的简洁方法

Clean way of writing several nested if-else with number ranges in Go

这段代码是有效的,但是我看的时候感觉不太好。我发现重构为更清晰或更简短的内容时遇到了麻烦。将代码分成几个 if-return 在这里似乎没有太大帮助。提示?谢谢!

if t < 0 {
    r = 0
} else if t >= 0 && t < 7.5 {
    if m >= 0 && m < 0.125 {
        r = 1
    } else {
        r = 2
    }
} else if t >= 7.5 && t < 10 {
    if m >= 0 && m < 0.125 {
        r = 1
    } else {
        r = 4
    }
} else if t >= 10 && t < 20 {
    if m >= 0 && m < 0.125 {
        r = 1
    } else if m >= 0.125 && m < 0.25 {
        r = 3
    } else {
        r = 4
    }
} else if t >= 20 && t < 22.5 {
    if m >= 0 && m < 0.125 {
        r = 7
    } else if m >= 0.125 && m < 0.375 {
        r = 3
    } else {
        r = 4
    }
} else if t >= 22.5 && t < 27.5 {
    if m >= 0 && m < 0.125 {
        r = 7
    } else if m >= 0.125 && m < 0.625 {
        r = 5
    } else {
        r = 6
    }
} else if t >= 27.5 {
    if m >= 0 && m < 0.25 {
        r = 7
    } else if m >= 0.25 && m < 0.625 {
        r = 5
    } else {
        r = 6
    }
}

简化外层if/else if/else去除冗余比较并转换为switch:

switch {
case t < 0:
    r = 0
case t < 7.5:
    if m >= 0 && m < 0.125 {
        r = 1
    } else {
        r = 2
    }
case t < 10:
    if m >= 0 && m < 0.125 {
        r = 1
    } else {
        r = 4
    }
case t < 20:
    if m >= 0 && m < 0.125 {
        r = 1
    } else if m >= 0.125 && m < 0.25 {
        r = 3
    } else {
        r = 4
    }
case t < 22.5:
    if m >= 0 && m < 0.125 {
        r = 7
    } else if m >= 0.125 && m < 0.375 {
        r = 3
    } else {
        r = 4
    }
case t < 27.5:
    if m >= 0 && m < 0.125 {
        r = 7
    } else if m >= 0.125 && m < 0.625 {
        r = 5
    } else {
        r = 6
    }
default:
    if m >= 0 && m < 0.25 {
        r = 7
    } else if m >= 0.25 && m < 0.625 {
        r = 5
    } else {
        r = 6
    }
}

可以对内部语句进行类似的修改。代码:

    if m >= 0 && m < 0.125 {
        r = 1
    } else {
        r = 2
    }

变为:

   switch {
   case m < 0:
       // r not changed
   case m < 0.125:
       r = 1
   default:
       r = 2
   }

查看这些值,您可以使用一些数据结构对范围检查进行编码:

type Rng struct {
   From,To float64
   V int
}

func (r Rng) In(val float64) bool { return val>=r.From && val<r.To }

type ARange struct {
   T Rng
   M []Rng  
   Def int // Default value for r if none of the M ranges match
}

var ranges=[]ARange{ {T:Rng{0,7.5}, M:[]Rng{ {0,0.125,1} }, Def: 2 },
  ...

然后,编写遍历 ranges 的每个元素并检查 tm 以查看是否有任何匹配项的 for 循环。