大量 if-else 的函数重构 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linquan
V2EX    问与答

大量 if-else 的函数重构

  •  
  •   linquan 2021-11-22 11:16:33 +08:00 4292 次点击
    这是一个创建于 1501 天前的主题,其中的信息可能已经有所发展或是发生改变。
    语言是 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     Solana     789 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 21:38 PVG 05:38 LAX 13:38 JFK 16:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86