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

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

  •  
  •   sunshinev ·
    sunshinev · 247 天前 · 7436 次点击
    这是一个创建于 247 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    第 1 条附言  ·  247 天前

    修正一下之前的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   247 天前   ❤️ 3
    if 包含 1,走 A
    if 包含 2,走 B
    GM
        2
    GM   247 天前   ❤️ 11
    这已经很好的逻辑了,简单易懂,你还想优化成什么样?

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

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

    x == 3 的时候,两个判断都是 true,AB 都运行
    Rekkles
        3
    Rekkles   247 天前   ❤️ 4
    x == 1 ? A : (X == 2 ? B : AB)
    gggxxxx
        4
    gggxxxx   247 天前   ❤️ 4
    如果是我的话,换成 switch 就行了。我不会纠结什么最优解,语意明确最重要。
    chogath
        5
    chogath   247 天前
    (function (x) { const dict = { 1: 'A', 2: 'B', 3: 'AB' }; return dict[x] } )(3)
    swikis
        6
    swikis   247 天前 via iPhone
    策略模式
    secondwtq
        7
    secondwtq   247 天前 via iPhone   ❤️ 7
    这不是史上最坑面试题 fizzbuzz 么……
    别问了,99.5%的程序员都不会的
    jadehare
        8
    jadehare   247 天前
    if(n / 2 >= 1) B;
    if(n%2 == 1) A;
    icql
        9
    icql   247 天前   ❤️ 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   247 天前
    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) {
    beichenhpy
        11
    beichenhpy   247 天前 via Android
    @Rekkles 过分了
    across
        12
    across   247 天前
    上面那个位运算 if 的已经被占了,这个应该是最简洁明了的。

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

    自然的表达即“本来是什么意思就表达什么”。
    zjsxwc
        15
    zjsxwc   247 天前
    $f = [
    1 => (){A();},
    2 => (){B();},
    3 => (){A();B();},
    ];

    $f[x]();
    xiangyuecn
        16
    xiangyuecn   247 天前   ❤️ 1
    看眼神 😏😏😏😏😏😏😏😏

    if(x!=2){
    A()
    }else if(x!=1){
    B()
    }
    xiangyuecn
        17
    xiangyuecn   247 天前   ❤️ 1
    #16 应该不要 else

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

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

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

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

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

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

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


    我觉得越简单,用简单清晰的代码写出来就行了
    iceheart
        62
    iceheart   246 天前 via Android
    老老实实写,别搞花样
    dragonbuf
        63
    dragonbuf   246 天前
    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   246 天前
    一通下来,还是最朴素的最优雅。没有性能问题就不搞花的了,代码是给人看的
    diegozhu
        65
    diegozhu   246 天前
    1. 转 map:
    {1: "A", 2: "B", 3: "AB"}[X]
    2.
    lbyo
        66
    lbyo   246 天前
    @sunshinev #18 16 、17 的回答完全不符合题意啊,楼主你自己有没有搞清楚...
    13670515509
        67
    13670515509   246 天前
    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   246 天前
    @xiangyuecn 卧槽,优秀。
    slipper
        69
    slipper   246 天前
    如果以后还会加其他的判断情况,考虑扩展性,可以使用 visitor pattern,如果没有,直接写就很好了。
    shm7
        70
    shm7   246 天前
    其他值怎么处理,不考虑吗?
    crazyhorse
        71
    crazyhorse   246 天前
    function run(x) {
    const runner = [{
    x: [1,2],

    }]

    if(runA.indexOf)
    }
    crazyhorse
        72
    crazyhorse   246 天前
    //有后续扩展(更多条件和要执行的方法)
    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   246 天前 via Android
    分支或者查表,看应用场景吧。
    donaldsu
        74
    donaldsu   246 天前
    想到两个,不过都已经被占了😂
    1 、mask 位运算
    2 、switch case
    xiaoliu926
        75
    xiaoliu926   246 天前
    @Kamiyu0087 kotlin 大法好
    RickyC
        76
    RickyC   246 天前
    果然你们后端都是逻辑狂人
    SmiteChow
        77
    SmiteChow   245 天前
    你提到的才是最优雅的,其他都是 tricky
    northisland
        78
    northisland   235 天前 via Android
    x&0x01 and A() and false or y&0x02 and B() and false
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1143 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 18:23 · PVG 02:23 · LAX 11:23 · JFK 14:23
    ♥ Do have faith in what you're doing.