V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
linquan
V2EX  ›  问与答

大量 if-else 的函数重构

  •  
  •   linquan · 2021-11-22 11:16:33 +08:00 · 3792 次点击
    这是一个创建于 1081 天前的主题,其中的信息可能已经有所发展或是发生改变。
    语言是 c#,代码中有很多 if-else 的判断语句,就像这样:if (x==1) then func1... if (x==2) then func2... ...像这样有几十个。虽然看起来还算清楚,但是想用一种更加高效率的方式完成,能够减少代码量,或者提高运行速度。目前想到的是做一个 x 和 func 的映射,例如 map 等,然后这样时间复杂度就变成了 logn 。请问有没有更好的方法?
    26 条回复    2021-11-22 23:20:59 +08:00
    28Sv0ngQfIE7Yloe
        1
    28Sv0ngQfIE7Yloe  
       2021-11-22 11:19:38 +08:00
    1.策略工厂
    2.模板方法
    3.责任链
    ysc3839
        2
    ysc3839  
       2021-11-22 11:22:43 +08:00
    x 比较连续的话直接用数组,复杂度就是 O(1) 了。
    ipwx
        3
    ipwx  
       2021-11-22 11:28:43 +08:00
    如果是整数,可以用 switch 。编译器可能帮你直接转换成跳表(查表),也是 O(1) 的。
    zxlzy
        4
    zxlzy  
       2021-11-22 11:35:38 +08:00   ❤️ 1
    map 的时间复杂度是 1
    Jooooooooo
        5
    Jooooooooo  
       2021-11-22 11:35:59 +08:00   ❤️ 4
    这...除非是有上万个, 一般不考虑这种性能损耗.

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

    工作 1 年:策略模式

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

    就是 else 必须少用。

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

    ```
    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;
    }
    ```

    比逻辑与数据分离的表驱动代码更好一点。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2993 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 13:27 · PVG 21:27 · LAX 05:27 · JFK 08:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.