有没有一种方法可以缩短包含大量布尔比较的条件语句?

3

e.g

if("viewCategoryTree".equals(actionDetail)
                || "fromCut".equals(actionDetail)
                || "fromPaste".equals(actionDetail)
                || ("viewVendorCategory".equals(actionDetail))&&"viewCategoryTree".equals(vendorCategoryListForm.getActionOrigin())
                || ("viewVendorCategory".equals(actionDetail))&&"fromEdit".equals(vendorCategoryListForm.getActionOrigin())
                || "deleteSelectedItem".equals(actionDetail)
                || ("viewVendorCategory".equals(actionDetail))&&"fromLink".equals(vendorCategoryListForm.getActionOrigin())){
//do smth
}

我尝试过类似这样的东西。
if(check("deleteSelectedItem,viewCategoryTree,fromCut,fromPaste,{viewVendorCategory&&viewVendorCategory},{viewVendorCategory&&fromEdit},{viewVendorCategory&&fromLink}",actionDetail,actionOrigin)){
//do smth
}

public boolean check(String str, String ad, String ao){

    String oneCmp = "";
    String[] result = str.split(",");
    ArrayList adList = new ArrayList();
    ArrayList aoList = new ArrayList();
    for (int i=0; i<result.length; i++){
        oneCmp = result[i];
        Matcher m = Pattern.compile("\\{([^}]*)\\}").matcher(oneCmp);
        if(m.matches()){
            m.find();
            String agrp = m.group();
            String[] groupresult = agrp.split("[\\W&&[^!]]+");
            Boolean a = false;
            Boolean b = false;
            if(groupresult[0].startsWith("!")){
                a = !groupresult[0].substring(1).equals(ad);
            } else a = groupresult[0].equals(ad);
            if(groupresult[1].startsWith("!")){
                b = !groupresult[1].substring(1).equals(ao);
            }else b = groupresult[1].equals(ao);

            if(agrp.indexOf("&&")!=-1){
                if(!(a && b))return false;
            }
            else if(agrp.indexOf("||")!=-1){
                if(!(a || b))return false;
            }
        } else {
            if(oneCmp.indexOf("^")==-1){
                checklist(oneCmp,ad);
                        if(!checklist(oneCmp,ad))return false;
            }else{
            if(!checklist(oneCmp,ao))return false;
            }
        }
    }

    return false;
}

public boolean checklist(String str, String key){

    if(str.startsWith("!")){
        if(str.substring(1).equals(key))return false;
        }else { if (!str.substring(1).equals(key)) return false;
        }
    }

    return false;
}

有没有更好的方法来做这件事?谢谢。

你可以使用某种“包含”或“在其中”的函数吗? - Chris Pfohl
你应该在http://codereview.stackexchange.com上询问这个问题。 - Oscar Mederos
@Oscar他可能会问这个问题,但它仍然是与主题相关的。 - user1228
@Will 看一下Jeff的回答:http://meta.stackexchange.com/questions/82069/is-it-okay-to-have-a-stackexchange-site-that-is-a-subset-of-another-one - Oscar Mederos
@Oscar 说实话,这个问题不是关于“这是我的代码,好还是坏”的问题,而是关于缩短包含大量布尔比较的if语句的技巧。这更多是模式而不是实践。这绝对是这里的主题,可能也可以在codereview.SE上被考虑为主题。 - user1228
6个回答

2
将检查移动到一个以actionDetail为参数的方法中:
// Assumes vendorCategoryListForm is a member variable.
boolean check(String actionDetail) {
    return ("viewCategoryTree".equals(actionDetail)
            || "fromCut".equals(actionDetail)
            || "fromPaste".equals(actionDetail)
            || (("viewVendorCategory".equals(actionDetail))
                &&"viewCategoryTree".equals(vendorCategoryListForm.getActionOrigin()))
            || (("viewVendorCategory".equals(actionDetail))
                &&"fromEdit".equals(vendorCategoryListForm.getActionOrigin()))
            || "deleteSelectedItem".equals(actionDetail)
            || (("viewVendorCategory".equals(actionDetail))
                &&"fromLink".equals(vendorCategoryListForm.getActionOrigin())))
}

if (check(actionDetail)) {
    // do this
}

2
如何创建一个你需要测试的数组。然后使用以下代码:
arrayOfStrings = ["viewCategoryTree", ...]
match = false
for elem in arrayOfStrings:
   if elem == actionDetail:
       match = true
       break

数组的好处在于它很容易扩展:您可以静态和动态地轻松添加/删除元素。


1

请注意这篇文章

不限语言 感谢 Galwegian

需要帮助请查看 箭头代码展开

   1. Replace conditions with guard clauses.
   2. Decompose conditional blocks into seperate functions.
   3. Convert negative checks into positive checks.

0
if(isValidActionDetail(actionDetail)
            || (isValidActionDetail(actionDetail)
            && ("viewCategoryTree".equals(vendorCategoryListForm.getActionOrigin()) 
                || "fromEdit".equals(vendorCategoryListForm.getActionOrigin())  
                || "fromLink".equals(vendorCategoryListForm.getActionOrigin())))){

//do smth
    }
}

public static boolean isValidActionDetail (String actionDetail) {
    return "viewCategoryTree".equals(actionDetail) || "fromCut".equals(actionDetail) 
           || "fromPaste".equals(actionDetail) || "deleteSelectedItem".equals(actionDetail) 
           || "viewVendorCategory".equals(actionDetail);
}

你可以按照上述方式进行分解,这是重构逻辑的第一步。


0
说实话,那个代码已经不太易读了。我建议把条件检查封装到某个类型的属性中,像这样:if (control.IsApplicable) { // do smth }
不管你用一个参数还是两个参数进行参数化,都无所谓。但我认为更好的解决方案是有一个匹配项数组,可以对其进行测试,如果匹配则返回 true。

0

我认为你不会在不增加复杂性的情况下改进这个问题,无论是从表示条件的符号还是评估它们的“引擎”实现的角度来看都是如此。

表示条件的符号问题是:虽然您最终可能用更少的字符表达条件,但其他人阅读您的代码时必须找出那个奇怪的字符串字面意思是什么。

此外,任何聪明的操作都可能对性能产生影响。例如,你的尝试每次调用check都会编译和应用正则表达式多次。

我的建议是坚持你现在所拥有的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接