linquan
V2EX  ›  问与答

大量 if-else 的函数重构

  •  
  •   linquan · Nov 22, 2021 · 4919 views
    This topic created in 1808 days ago, the information mentioned may be changed or developed.
    语言是 c#,代码中有很多 if-else 的判断语句,就像这样:if (x==1) then func1... if (x==2) then func2... ...像这样有几十个。虽然看起来还算清楚,但是想用一种更加高效率的方式完成,能够减少代码量,或者提高运行速度。目前想到的是做一个 x 和 func 的映射,例如 map 等,然后这样时间复杂度就变成了 logn 。请问有没有更好的方法?
    26 replies  •  2021-11-22 23:20:59 +08:00
    28Sv0ngQfIE7Yloe
    28Sv0ngQfIE7Yloe
    Nov 22, 2021
    1
    1.策略工厂
    2.模板方法
    3.责任链
    ysc3839
    ysc3839
    Nov 22, 2021
    2
    x 比较连续的话直接用数组,复杂度就是 O(1) 了。
    ipwx
    ipwx
    Nov 22, 2021
    3
    如果是整数,可以用 switch 。编译器可能帮你直接转换成跳表(查表),也是 O(1) 的。
    zxlzy
    zxlzy
    Nov 22, 2021❤️1
    4
    map 的时间复杂度是 1
    Jooooooooo
    Jooooooooo
    Nov 22, 2021❤️4
    5
    这...除非是有上万个, 一般不考虑这种性能损耗.

    从可读性的角度出发优化吧.
    shijieheping
    shijieheping
    Nov 22, 2021
    6
    表驱动,逻辑与数据分离
    linquan
    linquan
    OP
    Nov 22, 2021
    7
    @zxlzy 这个我也挺懵逼的,在 c++好像是 hashmap 复杂度 1 ,直接用哈希函数实现; map 用红黑树,复杂度 logn
    DawnMoon
    DawnMoon
    Nov 22, 2021 via Android
    8
    如果是 c 的话,可以考虑结构体数组+函数指针。
    C#应该可以直接用字典实现吧?
    fregie
    fregie
    Nov 22, 2021❤️3
    10
    逻辑清楚和简单才是一个中大型软件工程最高优先级,没必要的高效率和低代码量只会徒增项目的维护成本。
    DTCPSS
    DTCPSS
    Nov 22, 2021❤️1
    11
    ```
    async Task DoSomething(Direction direction)
    {
    Task task = direction switch
    {
    Direction.Up => GoNorthAsync(),
    Direction.Right => GoEastAsync(),
    Direction.Down => GoSouthAsync(),
    Direction.Left => GoWestAsync(),
    _ => throw new ArgumentOutOfRangeException(nameof(direction), $"Not expected direction value: {direction}"),
    };
    await task;
    }
    ```
    telung
    telung
    Nov 22, 2021
    12
    重构 if else 并不能提高代码运行速度
    BeautifulSoap
    BeautifulSoap
    Nov 22, 2021 via Android
    13
    lz 你这想法不就是表驱动吗,这么做没问题的
    lightjiao
    lightjiao
    Nov 22, 2021
    14
    别搞那么多抽象,求求了,我们项目代码七八层 OOP 看吐了
    只要不是那种低效率或者完全没有拆分函数的 if else ,没啥毛病啊,阅读起来简单,好维护,运行效率有保证,还要啥自行车
    Cloutain
    Cloutain
    Nov 22, 2021
    15
    switch 不就行了 还用啥 map ,switch 下要么变跳转表,要变索引表,要么变树,充分利用编译器的特性 不要自己折腾
    wizzer
    wizzer
    Nov 22, 2021
    16
    好好优化业务实现,不比优化掉 if else 更能提升性能?
    OysterQAQ
    OysterQAQ
    Nov 22, 2021
    17
    if else 比你说的什么 map 快多了,不是一个量级,==在汇编就一句话 对应机器级别的一条二进制指令 然后根据结果无条件跳转 提升运行速度是不可能的
    ipwx
    ipwx
    Nov 22, 2021
    18
    @OysterQAQ 你说错了吧,switch-case 才是跳表。。。。if-else 串联 1000 个那还是得慢。
    OysterQAQ
    OysterQAQ
    Nov 22, 2021
    19
    基本任何对于工程性的优化都不会提高运行速度,例如 magic 数,立即数肯定是比其他寻址方式快得多的。多 if else 需要考虑对于工程性上的优化,代码的可读性 可维护性
    OysterQAQ
    OysterQAQ
    Nov 22, 2021
    20
    @ipwx 你说的对 if 串联是会多次判断,我是说 if/switch 一次判断和 map 一次映射的比较
    MatDK
    MatDK
    Nov 22, 2021
    21
    你可以做 1 个 functionarray[n]={func0,func1,..../}
    然后按直接 functionarray[x](params)就行了....
    PiersSoCool
    PiersSoCool
    Nov 22, 2021
    22
    刚工作:不知道

    工作 1 年:策略模式

    工作 N 年:只要能看懂,写起来不麻烦就行
    kisshere
    kisshere
    Nov 22, 2021
    23
    DrakeXiang
    DrakeXiang
    Nov 22, 2021
    24
    不考虑性能,几十个 if else 我看着也受不了。。
    tool2d
    tool2d
    Nov 22, 2021
    25
    函数里光是多个 if ,代码也挺好理解的。

    就是 else 必须少用。

    C++会把大型 switch case 优化成二分查找,相当于 map 的 logn ,但是恕我直言,这对性能压根不重要。除非代码是自动生成的几百几千个 IF ,那另说。
    c0xt30a
    c0xt30a
    Nov 22, 2021
    26
    对我来讲,这样直白的代码

    ```
    int func( int i )
    {
    return i == 1 ? func1( i ) :
    i == 2 ? func2( i ) :
    i == 3 ? func3( i ) :
    i == 4 ? func4( i ) :
    i == 5 ? func5( i ) :
    0;
    }
    ```

    比逻辑与数据分离的表驱动代码更好一点。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1391 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 18:57 · PVG 02:57 · LAX 10:57 · JFK 13:57
    ♥ Do have faith in what you're doing.