Обработка (2 рейза до n) -1 условий - PullRequest
1 голос
/ 10 ноября 2010

У меня один логический вопрос.У меня есть коллекция объектов сотрудников. Имеются 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;
    }

Теперь, если мне нужно сработать сарайски, я должен написать как минимум 5 условий.

Это другой способ сделатьэто?

Ответы [ 7 ]

2 голосов
/ 10 ноября 2010

Есть много способов сделать это, но так как вы не указали один конкретный язык и так как я не чувствую себя квалифицированным, чтобы судить о вашем стиле кодирования, вот тот, который сохраняет общую форму вашего кода, демонстрируя при этомлучшая логика:

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 голос
/ 10 ноября 2010

Перед написанием кода убедитесь, что вы достаточно ясно разбираетесь в бизнес-логике. Согласно вашему коду, я вижу, что вы хотите проверить, имеют ли 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);
1 голос
/ 10 ноября 2010

Как насчет этого? Идея хорошо масштабируется для большего количества фильтров, за исключением того, что само отображение основано на конвенции (имя - имя).

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? Какое значение используется в этом случае?

1 голос
/ 10 ноября 2010

Вы можете проверить критерии индивидуально и вести подсчет совпадений.Таким образом, вам нужны только 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
}
1 голос
/ 10 ноября 2010

Начните с предположения, что у вас есть совпадение, а затем примените каждый критерий один за другим.

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) &&
    ...
   )
1 голос
/ 10 ноября 2010

Вы можете объединить свои условия фильтрации и получить единый оператор, который кодирует все параметры:

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, если нет, то проверка выполняется для соответствующего значения в emp и true только если этот чек true.

0 голосов
/ 10 ноября 2010

Проверьте каждый вопрос индивидуально и используйте набор битов для кодирования комбинаций ответов.

Это приводит к более чистому коду, потому что вы тестируете каждый критерий только один раз, он компактен, но удобен для чтения, и все же вы можете легко подключить код для обработки каждой комбинации.И это тоже быстро.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 в карте, которая отображает хэш-код в класс команд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...