处理(2加至n)-1条件

时间:2010-11-10 05:22:10

标签: c# logic

我有一个合乎逻辑的问题。我有员工对象的集合 有3个过滤标准条件有处理 对于例如员工姓名,办公室名称,工资。

现在这些过滤条件应该匹配(员工姓名和/或办公室名称和/或工资)

所以在这里我必须写(2加n)-1如果有条件来处理这种情况。

还有其他方法可以做到这一点。 对于(员工姓名和/或办公室名称)条件我正在做以下

if (criteria.EmpName != "" && criteria.OfficeName != "")
    {  
      if (emp.EmpName == criteria.EmpName && emp.OfficeName == criteria.OfficeName) 
        {
              bIsMatch = true;
         }
    }
    else
    {
          if (criteria.EmpName != "" && emp.EmpName == criteria.EmpName)
             bIsMatch = true;
          else if (criteria.OfficeName != "" && emp.OfficeName == criteria.OfficeName)
            bIsMatch = true;
    }

现在如果必须处理saraly,我也写了最少5个条件。

以其他方式去做吗?

7 个答案:

答案 0 :(得分:2)

有很多方法可以做到这一点,但由于你没有指定一种特定的语言,因为我觉得没有资格判断你的编码风格,所以这里保留了代码的一般形式,同时展示了一些更好的逻辑:

bool bIsMatch = true;
if (criteria.EmpName != "" && criteria.EmpName != emp.EmpName) {
    bIsMatch = false;
} else if (criteria.OfficeName != "" && criteria.OffIceName != emp.OfficeName) {
    bIsMatch = false;
} /* Repeat for as many conditions as there are */

if (bIsMatch) {
    /* None of the checks above failed */
}

答案 1 :(得分:1)

您可以配置过滤条件并使用单个语句对所有参数进行编码:

if( (criteria.EmpName.equals("") || criteria.EmpName.equals(emp.EmpName))
    && (criteria.OfficeName.equals("") || criteria.OfficeName.equals(emp.OfficeName))
    && (criteria.Salary.equals("") || criteria.Salary.equals(emp.Salary)))

在每个AND-ed表达式中,首先检查过滤器是否为空,如果该块将导致true,如果不是,则检查是针对{{1}中的相应值执行的。仅当该检查为emp时才会true

答案 2 :(得分:1)

首先假设你有一个匹配,然后逐个应用每个标准。

bIsMatch = true;

if (bIsMatch && criteria.EmpName    != "") bIsMatch = emp.EmpName    == criteria.EmpName;
if (bIsMatch && criteria.OfficeName != "") bIsMatch = emp.OfficeName == criteria.OfficeName;
// ...

或者,编写一个执行匹配的辅助函数。

bool IsMatch(String criterion, String value)
{
    return criterion == "" || criterion == value;
}

然后你可以在一个大的if语句中做所有事情:

if (IsMatch(criteria.EmpName,    emp.EmpName)    &&
    IsMatch(criteria.OfficeName, emp.OfficeName) &&
    ...
   )

答案 3 :(得分:1)

您可以单独检查标准并保持匹配计数。这样你只需要n条件:

int matches = 0;

if (criteria.EmpName != "" && emp.EmpName == criteria.EmpName)
  matches++;
// similar code for other criteria

if (matches >= 2) { // as many matches as required
  // succeeded
}

答案 4 :(得分:1)

这个怎么样?除了映射本身是约定(名称 - 名称)之外,这个想法可以很好地扩展到更多过滤器。

var map = new Dictionary<string, string>
              {
                { criteria.EmpName, emp.EmpName },       
                { criteria.OfficeName, emp.OfficeName},
                { criteria.ThirdProp, emp.ThirdProp }
              };

bIsMatch = dict.All(kvp => string.IsNullOrEmpty(kvp.Key) || kvp.Key == kvp.Value);

我会质疑整体设计;有些东西看起来不对。你会如何处理你提到的Salary字段?当然,那不是string?在这种情况下使用的哨兵价值是多少?

答案 5 :(得分:1)

在编写代码之前,请确保您对业务逻辑足够清楚。根据您的代码,我可以看到您要检查empcriteria是否具有相同的EmployeeNameOfficeName,任何属性都被认为是相同的如果它是string.Empty。在你清楚之后,代码将非常清楚。我们走了:

public static bool EmptyOrEquals(this string one, string another)
{
    return string.IsNullOrEmpty(another) || one.Equals(another);
}
bIsMatch = emp.EmpName.EmptyOrEquals(criteria.EmpName) 
            && emp.OfficeName.EmptyOrEquals(criteria.OfficeName);

答案 6 :(得分:0)

单独测试每个问题并使用一组位来编码答案组合。

这会产生更清晰的代码,因为您只测试一次标准,它既紧凑又可读,但您可以轻松插入代码来处理每个组合。它也很快。 O(n)测试所有标准,O(1)找到实际组合。

对于少量固定数量的标准,您可以手动推送位。对于许多标准或扩展的解决方案,请使用java.util.BitSet

推进示例:

int bits = 0;

if (...criteria 1...) {
    bits = 1;
}

if (...criteria 2...) {
    bits |= 2;
}

if (...bits 3...) {
    bits |= 4;
}

switch (bits) {
case 0: // no criteria matched
    ;
case 1: // criteria 1 matched
    ;
case 2: // criteria 2 matched
    ;
case 3: // criteria 1 AND 2 matched
    ;
case 4: // criteria 3 matched
    ;
case 5: // criteria 1 AND 3 matched
    ;
case 6: // criteria 2 AND 3 matched
    ;
case 7: // criteria 1 AND 2 AND 3 matched
    ;
} 

您可以使用java.util.BitSet来概括此解决方案来操作n个条件的位(当n> 64时有用!)。为了便于快速查找,请将每个BitSet组合的哈希值存储在将哈希码映射到命令类的映射中。