Чистый способ записи нескольких вложенных if-else с диапазонами чисел в Go - PullRequest
1 голос
/ 13 апреля 2020

Этот фрагмент кода эффективен, но я не чувствую себя хорошо, когда читаю его. Я нахожу проблемы с рефакторингом в нечто более разборчивое или короткое. Разбивка кода на несколько 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
    }
}

Ответы [ 2 ]

5 голосов
/ 13 апреля 2020

Упрощение внешнего if / else, если / else удаление избыточных сравнений и преобразование в переключатель:

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
   }
1 голос
/ 13 апреля 2020

Глядя на значения, вы можете кодировать проверки диапазона с некоторыми структурами данных:

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 },
  ...

Затем напишите for-l oop, который проходит через каждый элемент ranges и проверяет t и m, чтобы увидеть, есть ли совпадения.

...