V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sunshinev
V2EX  ›  程序员

请教一个优雅的逻辑方案,=1 走 A ,=2 走 B, =3 走 AB 两个,怎么写比较好?不限语言

  •  
  •   sunshinev ·
    sunshinev · 2020-11-24 11:58:57 +08:00 · 8430 次点击
    这是一个创建于 1220 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请教一个最优逻辑方案,=1 走 A,=2 走 B, =3 走 AB 两个,怎么写比较好?

    if x==1 {
    	A
    }elseif x==2 {
    	B
    }else {
    	A
        B
    }
    

    要求如上,有优雅的写法吗?

    第 1 条附言  ·  2020-11-24 14:59:21 +08:00

    修正一下之前的Demo,想要的逻辑如下

    if x==1 {
    	A
    }elseif x==2 {
    	B
    }elseif x==3 {
    	A
            B
    }
    
    78 条回复    2020-12-06 16:28:26 +08:00
    CommandZi
        1
    CommandZi  
       2020-11-24 12:04:35 +08:00   ❤️ 3
    if 包含 1,走 A
    if 包含 2,走 B
    GM
        2
    GM  
       2020-11-24 12:05:06 +08:00   ❤️ 11
    这已经很好的逻辑了,简单易懂,你还想优化成什么样?

    如果只是单纯想减少代码行数(然鹅可读性会变差)的话,考虑位运算:

    if x & 1 {
    A
    }
    if x & 2 {
    B
    }

    x == 3 的时候,两个判断都是 true,AB 都运行
    Rekkles
        3
    Rekkles  
       2020-11-24 12:06:24 +08:00   ❤️ 4
    x == 1 ? A : (X == 2 ? B : AB)
    gggxxxx
        4
    gggxxxx  
       2020-11-24 12:06:45 +08:00   ❤️ 4
    如果是我的话,换成 switch 就行了。我不会纠结什么最优解,语意明确最重要。
    chogath
        5
    chogath  
       2020-11-24 12:10:29 +08:00
    (function (x) { const dict = { 1: 'A', 2: 'B', 3: 'AB' }; return dict[x] } )(3)
    swikis
        6
    swikis  
       2020-11-24 12:12:40 +08:00 via iPhone
    策略模式
    secondwtq
        7
    secondwtq  
       2020-11-24 12:13:19 +08:00 via iPhone   ❤️ 7
    这不是史上最坑面试题 fizzbuzz 么……
    别问了,99.5%的程序员都不会的
    jadehare
        8
    jadehare  
       2020-11-24 12:14:34 +08:00
    if(n / 2 >= 1) B;
    if(n%2 == 1) A;
    icql
        9
    icql  
       2020-11-24 12:25:27 +08:00   ❤️ 1
    逻辑多的话可以用质数乘积,A=2,B=3,C=5,x%A==0 执行 A,x%B==0 执行 B,x%C==0 执行 C,例如 x=6,就会执行 AB,x=30 就会执行 ABC,对外用枚举封装需要的逻辑组合的质数乘积😄
    Mutoo
        10
    Mutoo  
       2020-11-24 12:28:01 +08:00
    A = 1
    B = 2
    C = 4
    D = 8

    Input = A | B // equals 3

    if (Input & A) /* DO A */
    if (Input & B) /* DO B */
    if (Input & C) /* DO C */
    if (Input & D) /* DO D */

    将 ABCD 编码成 2 的 n 次方,然后可以用 | 运算来组合配置项,用 & 运算来检查配置项,

    这在 C 编程中很常用,例如:

    if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) != 0) {
    uselessVisitor
        11
    uselessVisitor  
       2020-11-24 12:31:30 +08:00 via Android
    @Rekkles 过分了
    across
        12
    across  
       2020-11-24 12:46:23 +08:00
    上面那个位运算 if 的已经被占了,这个应该是最简洁明了的。

    从 C 升级到 C++折腾版后,还有一个 Map<fnPtr,fnPtr>(Condition,Action),就是判断条件比较复杂时,挨个遍历 map 执行 condition,执行 action···· 按简单数值比较场景来说就不用了。
    mooczz
        13
    mooczz  
       2020-11-24 12:52:00 +08:00 via iPhone
    逻辑与运算,刚好是 1 10 11
    geelaw
        14
    geelaw  
       2020-11-24 12:59:09 +08:00 via iPhone
    这取决于 1 、2 、3 的含义:如果这是一个位映射枚举,则用位运算 #2 是自然的解法;如果这不具有位映射枚举的含义,则楼主本来的写法自然。

    自然的表达即“本来是什么意思就表达什么”。
    zjsxwc
        15
    zjsxwc  
       2020-11-24 13:01:47 +08:00
    $f = [
    1 => (){A();},
    2 => (){B();},
    3 => (){A();B();},
    ];

    $f[x]();
    xiangyuecn
        16
    xiangyuecn  
       2020-11-24 13:06:10 +08:00   ❤️ 1
    看眼神 😏😏😏😏😏😏😏😏

    if(x!=2){
    A()
    }else if(x!=1){
    B()
    }
    xiangyuecn
        17
    xiangyuecn  
       2020-11-24 13:06:54 +08:00   ❤️ 1
    #16 应该不要 else

    if(x!=2){
    A()
    }

    if(x!=1){
    B()
    }
    sunshinev
        18
    sunshinev  
    OP
       2020-11-24 13:19:11 +08:00
    @xiangyuecn 厉害啊,这脑回路
    sunshinev
        19
    sunshinev  
    OP
       2020-11-24 13:19:23 +08:00
    @GM 能用位运算的都是大神
    sunshinev
        20
    sunshinev  
    OP
       2020-11-24 13:20:09 +08:00
    @Mutoo 大神大神
    sunshinev
        21
    sunshinev  
    OP
       2020-11-24 13:20:53 +08:00
    @Rekkles 三元运算符👍,go 木有
    DoubleShut
        22
    DoubleShut  
       2020-11-24 13:21:41 +08:00
    花里胡哨的,switch case 不行吗?
    sunshinev
        23
    sunshinev  
    OP
       2020-11-24 13:22:31 +08:00
    @secondwtq 学习了,推荐大家可以看下 簡單的 FizzBuzz 藏有 深度(google 面試題)
    yaoweilei
        24
    yaoweilei  
       2020-11-24 13:23:09 +08:00
    go="A" if x==1 else "B" if x==2 else "C"
    Lemeng
        25
    Lemeng  
       2020-11-24 13:23:26 +08:00
    文明人讲究优雅。
    leo108
        26
    leo108  
       2020-11-24 13:45:09 +08:00
    switch (x) {
    case 3:
    // no break
    case 1:
    A;
    if (x === 1) {
    break;
    }
    case 2:
    B;
    break;
    }
    antiquezzz
        27
    antiquezzz  
       2020-11-24 13:56:50 +08:00
    兄弟不会真的以为会写 FizzBuzz 很难得吧
    rainman777
        28
    rainman777  
       2020-11-24 14:05:06 +08:00
    ```
    if (n & 0x01)
    fun_a();
    if (n & 0x02)
    fun_b();

    ```
    hws8033856
        29
    hws8033856  
       2020-11-24 14:15:07 +08:00   ❤️ 1
    为什么你们包括 LZ 都不按题目要求来?
    不是=3 才执行 AB 么?
    你们怎么都是除=1 和=2 以外的其他值都执行 AB ?
    Jooooooooo
        30
    Jooooooooo  
       2020-11-24 14:25:39 +08:00
    最优的解法最容易看懂
    shenjies88
        31
    shenjies88  
       2020-11-24 14:32:48 +08:00   ❤️ 2
    这就是一个很简单的问题,切勿过度设计过度猜疑,if 或者 switch 即可
    marcong95
        32
    marcong95  
       2020-11-24 14:48:36 +08:00
    @hws8033856 #29 因为楼主的提供的样例里面就是 else { AB },那么问题来了,到底是 else AB 呢,还是=3 AB 呢,如果 x = 4 呢,楼主这题似乎已经有这个坑了

    若 x 属于 { 1, 2, 3 },那位运算+短路求值看着还挺舒服

    x & 1 && A()
    x & 2 && B()
    northisland
        33
    northisland  
       2020-11-24 15:00:33 +08:00
    一条搞定,但是很鬼畜,可读性不高。
    ```
    #include <ciso646>

    x&0x01 and A() or y&0x02 and B();
    ```
    我宁愿展开:
    if (x==1) A()
    else if (x==2) B()
    else if (x==3) {A(); B();}
    sunshinev
        34
    sunshinev  
    OP
       2020-11-24 15:01:00 +08:00
    其实看到很多位运算方案,但是总觉得位运算看起来很短,但是不是很容易理解~可能我还没找到窍门
    lloydsheng
        35
    lloydsheng  
       2020-11-24 15:03:37 +08:00
    如果没有性能问题,写的越清晰易懂越好
    terence4444
        36
    terence4444  
       2020-11-24 15:04:36 +08:00 via iPhone
    按 bit 开关判断即可
    1A 2B 4C 8D 16F
    zlowly
        37
    zlowly  
       2020-11-24 15:05:52 +08:00
    那要看不同场景下优雅是怎么定义了。如果这是在一个追求性能的的核心代码 /引擎之类的里,肯定是有优化空间;如果只是个普通代码片段,楼主本身的代码就没什么问题;如果是在业务逻辑代码里,可考虑的地方就多了,常见的是日后考虑调整或扩展=4=5 之类情况,有可能是更复杂的 ABCBA 执行情况等等,为了可读性和可维护性这时候上模式设计都是可以的。
    hws8033856
        38
    hws8033856  
       2020-11-24 15:06:37 +08:00
    @marcong95 所以我才说“包括 LZ” 都不按题目要求来
    只论代码长短,应该没有比你这个更短的了
    不过我始终认为所谓代码的优雅,应该更多要看重代码的可读性
    你这里用逻辑运算符来替代分支,就是很严重的破坏可读性,不优雅
    lx0758
        39
    lx0758  
       2020-11-24 15:16:02 +08:00
    位运算
    artikle
        40
    artikle  
       2020-11-24 15:22:48 +08:00   ❤️ 4
    if(x==1||x==3)
    A();
    if(x==2||x==3)
    B();
    sunshinev
        41
    sunshinev  
    OP
       2020-11-24 15:27:11 +08:00
    @artikle 其实我现在用的就是你的方案
    vitoliu
        42
    vitoliu  
       2020-11-24 15:27:55 +08:00
    用模式来做处理不是更好吗,推荐组合模式
    Kamiyu0087
        43
    Kamiyu0087  
       2020-11-24 15:30:12 +08:00   ❤️ 1
    when (x) {
    1 -> A()
    2 -> B()
    3 -> {
    A()
    B()
    }
    }
    marcong95
        44
    marcong95  
       2020-11-24 15:41:20 +08:00
    @hws8033856 #38 刚刚的确看漏了你的“包括”,

    我的方案只是代码本身有蜜汁对称性,看着爽。的确是牺牲了可读性,以及没有处理 x 在 123 以外的情况
    hst001
        45
    hst001  
       2020-11-24 16:11:38 +08:00
    你这问题,还刚好 123,就是设计考位运算的题吧
    cambria
        46
    cambria  
       2020-11-24 16:12:40 +08:00
    如果 x 取值只有 1,2,3 的话可以这么写( python):

    if (x % 2):
    A()
    if (x // 2):
    B()
    supuwoerc
        47
    supuwoerc  
       2020-11-24 17:18:17 +08:00
    x==1?a:x==2?b:x==3?a&b:null;
    wnpllrzodiac
        48
    wnpllrzodiac  
       2020-11-24 17:31:47 +08:00 via Android
    位操作?最低位表示 a 第二位表示 b.
    imn1
        49
    imn1  
       2020-11-24 18:10:45 +08:00
    x&1: A
    (x>>1)&1: B
    vhysug01
        50
    vhysug01  
       2020-11-24 18:14:02 +08:00 via iPhone
    查表
    skrskrskrskr
        51
    skrskrskrskr  
       2020-11-24 18:16:31 +08:00
    这一看就是工作不饱和
    xumng123
        52
    xumng123  
       2020-11-24 18:52:14 +08:00 via iPhone
    查表即可
    ychost
        53
    ychost  
       2020-11-24 19:10:18 +08:00
    Map funcMap = {1:A,2:B,3:A&B}
    lovecy
        54
    lovecy  
       2020-11-24 19:23:23 +08:00
    let funcMap = new Map([[1, func A], [2, func B], [3, func C]]);
    funcMap.get(x)();
    manymobi
        55
    manymobi  
       2020-11-24 19:47:43 +08:00
    我觉得 你在考虑思想, 上面这个问题太局限了, 可以看看 spirng HttpMessageConverter
    woahishui
        56
    woahishui  
       2020-11-24 20:02:35 +08:00 via Android
    策略模式加命令模式
    nocrush
        57
    nocrush  
       2020-11-24 20:28:36 +08:00
    搞一个 map
    phpIsNumberOne
        58
    phpIsNumberOne  
       2020-11-24 20:44:01 +08:00
    goto
    jinliming2
        59
    jinliming2  
       2020-11-24 20:52:27 +08:00
    支持 Excel 吗?
    =SWITCH(A1, 1, "A", 2, "B", 3, "AB", "other")
    yeyu1989
        60
    yeyu1989  
       2020-11-24 21:33:30 +08:00
    decode(x,1,A,2,B,3,AB)
    bbxiong
        61
    bbxiong  
       2020-11-24 23:23:37 +08:00
    if x == 1 then
    a
    elseif x == 2 then
    b
    elseif x == 3 then
    a b
    end


    我觉得越简单,用简单清晰的代码写出来就行了
    iceheart
        62
    iceheart  
       2020-11-25 08:48:27 +08:00 via Android
    老老实实写,别搞花样
    dragonbuf
        63
    dragonbuf  
       2020-11-25 09:45:04 +08:00
    1 A B C 的逻辑封装 helper
    ALogicHelper{}
    BLoginHelper{}
    CLoginHelper{}

    2 根据用途挑选 helper 组成 handler

    3 handler 注册进 factory
    DemoFatoryHandlerRegistry{1:AHandler, 2:Bhandler,3ABHandler}

    4 根据 id 获得 handler 接口
    DemoFactory::fromId(int id)->getHandler():HandlerInterface

    5 根据接口处理数据
    HandlerInterface->dosomething();
    someonedeng
        64
    someonedeng  
       2020-11-25 09:53:42 +08:00
    一通下来,还是最朴素的最优雅。没有性能问题就不搞花的了,代码是给人看的
    diegozhu
        65
    diegozhu  
       2020-11-25 09:59:53 +08:00
    1. 转 map:
    {1: "A", 2: "B", 3: "AB"}[X]
    2.
    lbyo
        66
    lbyo  
       2020-11-25 10:29:52 +08:00
    @sunshinev #18 16 、17 的回答完全不符合题意啊,楼主你自己有没有搞清楚...
    13670515509
        67
    13670515509  
       2020-11-25 10:49:57 +08:00
    js
    let obj = { 1: [A], 2: [B], 3: [A, B] }
    obj[x] && Array.isArray(obj[x]) && obj[x].forEach(fn => {typeof fn === 'function' && fn()})
    godwinma
        68
    godwinma  
       2020-11-25 11:11:43 +08:00
    @xiangyuecn 卧槽,优秀。
    slipper
        69
    slipper  
       2020-11-25 11:51:38 +08:00
    如果以后还会加其他的判断情况,考虑扩展性,可以使用 visitor pattern,如果没有,直接写就很好了。
    shm7
        70
    shm7  
       2020-11-25 13:21:46 +08:00
    其他值怎么处理,不考虑吗?
    crazyhorse
        71
    crazyhorse  
       2020-11-25 13:23:35 +08:00
    function run(x) {
    const runner = [{
    x: [1,2],

    }]

    if(runA.indexOf)
    }
    crazyhorse
        72
    crazyhorse  
       2020-11-25 13:32:08 +08:00
    //有后续扩展(更多条件和要执行的方法)
    function a() {console.log('a')}
    function b() {console.log('a')}
    function run(x) {
    const runners = [{
    x: [1,2],
    func: a,
    },{
    x: [2,3],
    func: b,
    }]

    runners.forEach((runner) => {
    if(runner.x.indexOf(x) !== -1)
    runner['func']();
    })
    }

    //固定 ab 但是条件有后续扩展
    function run(x) {
    const runA = [1,2];
    const runB = [2,3];

    if(runA.indexOf(x) !== -1)
    a();

    if(runB.indexOf(x) !== -1)
    a();
    }
    raaaaaar
        73
    raaaaaar  
       2020-11-25 15:54:43 +08:00 via Android
    分支或者查表,看应用场景吧。
    donaldsu
        74
    donaldsu  
       2020-11-25 16:19:36 +08:00
    想到两个,不过都已经被占了😂
    1 、mask 位运算
    2 、switch case
    xiaoliu926
        75
    xiaoliu926  
       2020-11-25 19:26:42 +08:00
    @Kamiyu0087 kotlin 大法好
    RickyC
        76
    RickyC  
       2020-11-25 23:03:33 +08:00
    果然你们后端都是逻辑狂人
    SmiteChow
        77
    SmiteChow  
       2020-11-26 10:38:34 +08:00
    你提到的才是最优雅的,其他都是 tricky
    northisland
        78
    northisland  
       2020-12-06 16:28:26 +08:00 via Android
    x&0x01 and A() and false or y&0x02 and B() and false
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3040 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 14:55 · PVG 22:55 · LAX 07:55 · JFK 10:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.