我有一个合乎逻辑的问题。我有员工对象的集合 有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个条件。
以其他方式去做吗?
答案 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)
在编写代码之前,请确保您对业务逻辑足够清楚。根据您的代码,我可以看到您要检查emp
和criteria
是否具有相同的EmployeeName
和OfficeName
,任何属性都被认为是相同的如果它是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组合的哈希值存储在将哈希码映射到命令类的映射中。