请教一个优雅的逻辑方案,=1 走 A ,=2 走 B, =3 走 AB 两个,怎么写比较好?不限语言 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
sunshinev
V2EX    程序员

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

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

    请教一个最优逻辑方案,=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) {
    zm8m93Q1e5otOC69
        11
    zm8m93Q1e5otOC69  
       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.
    hive
        66
    hive  
       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()})
    windsound
        68
    windsound  
       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     Solana     3485 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 10:40 PVG 18:40 LAX 03:40 JFK 06:40
    Do have faith in what you're doing.
    ubao 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