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

大量 if-else 的函数重构

  •  
  •   linquan · 66 天前 · 2651 次点击
    这是一个创建于 66 天前的主题,其中的信息可能已经有所发展或是发生改变。
    语言是 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
    Morii
        1
    Morii  
       66 天前
    1.策略工厂
    2.模板方法
    3.责任链
    ysc3839
        2
    ysc3839  
       66 天前
    x 比较连续的话直接用数组,复杂度就是 O(1) 了。
    ipwx
        3
    ipwx  
       66 天前
    如果是整数,可以用 switch 。编译器可能帮你直接转换成跳表(查表),也是 O(1) 的。
    zxlzy
        4
    zxlzy  
       66 天前   ❤️ 1
    map 的时间复杂度是 1
    Jooooooooo
        5
    Jooooooooo  
       66 天前   ❤️ 4
    这...除非是有上万个, 一般不考虑这种性能损耗.

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

    工作 1 年:策略模式

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

    就是 else 必须少用。

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

    ```
    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   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2848 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:51 · PVG 12:51 · LAX 20:51 · JFK 23:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.