📄 filter.cpp
字号:
int TValueFilter_string::operator()(const TExample &example) const
{
const TValue &val = example[position];
if (val.isSpecial())
return acceptSpecial;
char *value = caseSensitive ? const_cast<char *>(val.svalV.AS(TStringValue)->value.c_str())
: strToLower(val.svalV.AS(TStringValue)->value.c_str());
char *ref = caseSensitive ? const_cast<char *>(min.c_str()) : strToLower(min);
switch(oper) {
case Equal: return TO_BOOL(!strcmp(value, ref));
case NotEqual: return TO_BOOL(strcmp(value, ref));
case Less: return TO_BOOL(strcmp(value, ref) < 0);
case LessEqual: return TO_BOOL(strcmp(value, ref) <= 0);
case Greater: return TO_BOOL(strcmp(value, ref) > 0);
case GreaterEqual: return TO_BOOL(strcmp(value, ref) >= 0);
case Between: return TO_BOOL((strcmp(value, ref) >= 0) && (strcmp(value, max.c_str()) <= 0));
case Outside: return TO_BOOL((strcmp(value, ref) < 0) && (strcmp(value, max.c_str()) >= 0));
case Contains: return TO_BOOL(string(value).find(ref) != string::npos);
case NotContains: return TO_BOOL(string(value).find(ref) == string::npos);
case BeginsWith: return TO_BOOL(!strncmp(value, ref, strlen(ref)));
case EndsWith:
{ const int vsize = strlen(value), rsize = strlen(ref);
return TO_BOOL((vsize >= rsize) && !strcmp(value + (vsize-rsize), ref));
}
default:
return -1;
}
if (!caseSensitive) {
delete value;
delete ref;
}
}
TValueFilter_stringList::TValueFilter_stringList()
: TValueFilter(ILLEGAL_INT, -1),
values(mlnew TStringList()),
caseSensitive(true)
{}
TValueFilter_stringList::TValueFilter_stringList(const int &pos, PStringList bl, const int &accs, const int &op, const bool csens)
: TValueFilter(pos, accs),
values(bl),
caseSensitive(csens)
{}
int TValueFilter_stringList::operator()(const TExample &example) const
{
const TValue &val = example[position];
if (val.isSpecial())
return acceptSpecial;
char *value = caseSensitive ? const_cast<char *>(val.svalV.AS(TStringValue)->value.c_str())
: strToLower(val.svalV.AS(TStringValue)->value.c_str());
char *ref = caseSensitive ? NULL : new char[1024];
TStringList::const_iterator vi(values->begin()), ve(values->end());
for(; vi!=ve; vi++)
if (caseSensitive) {
if (!strcmp((*vi).c_str(), value))
break;
}
else {
if ((*vi).size() >= 1024)
raiseError("reference string too long (1023 characters is the limit)");
strcpy(ref, (*vi).c_str());
for(char *i = ref; *i; i++)
*i = tolower(*i);
if (!strcmp(ref, value))
break;
}
if (!caseSensitive) {
delete ref;
delete value;
}
return vi==ve ? 0 : 1;
}
#undef DIFFERENT
#undef LESS_EQUAL
#undef TO_BOOL
TFilter_values::TFilter_values(bool anAnd, bool aneg, PDomain dom)
: TFilter(aneg, dom),
conditions(mlnew TValueFilterList()),
conjunction(anAnd)
{}
TFilter_values::TFilter_values(PValueFilterList v, bool anAnd, bool aneg, PDomain dom)
: TFilter(aneg, dom),
conditions(v),
conjunction(anAnd)
{}
TValueFilterList::iterator TFilter_values::findCondition(PVariable var, const int &varType, int &position)
{
if (varType && (var->varType != varType))
raiseError("invalid variable type");
checkProperty(domain);
position = domain->getVarNum(var);
TValueFilterList::iterator condi(conditions->begin()), conde(conditions->end());
while((condi!=conde) && ((*condi)->position != position))
condi++;
return condi;
}
void TFilter_values::updateCondition(PVariable var, const int &varType, PValueFilter filter)
{
TValueFilterList::iterator condi = findCondition(var, varType, filter->position);
if (condi==conditions->end())
conditions->push_back(filter);
else
*condi = filter;
}
void TFilter_values::addCondition(PVariable var, const TValue &val, bool negate)
{
int position;
TValueFilterList::iterator condi = findCondition(var, TValue::INTVAR, position);
TValueFilter_discrete *valueFilter;
if (condi==conditions->end()) {
valueFilter = mlnew TValueFilter_discrete(position); // it gets wrapped in the next line
conditions->push_back(valueFilter);
}
else {
valueFilter = (*condi).AS(TValueFilter_discrete);
if (!valueFilter)
raiseError("addCondition(Value) con only be used for setting ValueFilter_discrete");
}
if (val.isSpecial())
valueFilter->acceptSpecial = 1;
else {
valueFilter->values->clear();
valueFilter->values->push_back(val);
}
valueFilter->negate = negate;
}
void TFilter_values::addCondition(PVariable var, PValueList vallist, bool negate)
{
int position;
TValueFilterList::iterator condi = findCondition(var, TValue::INTVAR, position);
if (condi==conditions->end())
conditions->push_back(mlnew TValueFilter_discrete(position, vallist));
else {
TValueFilter_discrete *valueFilter = (*condi).AS(TValueFilter_discrete);
if (!valueFilter)
raiseError("addCondition(Value) can only be used for setting ValueFilter_discrete");
else
valueFilter->values = vallist;
valueFilter->negate = negate;
}
}
void TFilter_values::addCondition(PVariable var, const int &oper, const float &min, const float &max)
{
updateCondition(var, TValue::FLOATVAR, mlnew TValueFilter_continuous(ILLEGAL_INT, oper, min, max));
}
void TFilter_values::addCondition(PVariable var, const int &oper, const string &min, const string &max)
{
updateCondition(var, STRINGVAR, mlnew TValueFilter_string(ILLEGAL_INT, oper, min, max));
}
void TFilter_values::addCondition(PVariable var, PStringList slist)
{
updateCondition(var, STRINGVAR, mlnew TValueFilter_stringList(ILLEGAL_INT, slist));
}
void TFilter_values::removeCondition(PVariable var)
{
int position;
TValueFilterList::iterator condi = findCondition(var, 0, position);
if (condi==conditions->end())
raiseError("there is no condition on value of '%s' in the filter", var->name.c_str());
conditions->erase(condi);
}
bool TFilter_values::operator()(const TExample &exam)
{ checkProperty(domain);
checkProperty(conditions);
TExample *example;
PExample wex;
if (domain && (domain != exam.domain)) {
example = mlnew TExample(domain, exam);
wex = example;
}
else
example = const_cast<TExample *>(&exam);
PITERATE(TValueFilterList, fi, conditions) {
const int r = (*fi)->call(*example);
if ((r==0) && conjunction)
return negate;
if ((r==1) && !conjunction)
return !negate; // if this one is OK, we should return true if negate=false and vice versa
}
// If we've come this far; if conjunction==true, all were OK; conjunction==false, none were OK
return conjunction!=negate;
}
PFilter TFilter_values::deepCopy() const
{
TValueFilterList *newValueFilters = mlnew TValueFilterList();
PValueFilterList wnewValueFilters = newValueFilters;
const_PITERATE(TValueFilterList, vi, conditions)
wnewValueFilters->push_back((*vi)->deepCopy());
TFilter *filter = mlnew TFilter_values(wnewValueFilters,conjunction,negate,domain);
PFilter wfilter = filter;
return wfilter;
}
/// Constructor; sets the example
TFilter_sameExample::TFilter_sameExample(PExample anexample, bool aneg)
: TFilter(aneg, anexample->domain), example(anexample)
{}
/// Chooses an examples (not) equal to the 'example'
bool TFilter_sameExample::operator()(const TExample &other)
{ return (example->compare(TExample(domain, other))==0)!=negate; }
/// Constructor; sets the example
TFilter_compatibleExample::TFilter_compatibleExample(PExample anexample, bool aneg)
: TFilter(aneg, anexample->domain),
example(anexample)
{}
/// Chooses an examples (not) compatible with the 'example'
bool TFilter_compatibleExample::operator()(const TExample &other)
{ return example->compatible(TExample(domain, other))!=negate; }
TFilter_conjunction::TFilter_conjunction()
: filters(mlnew TFilterList())
{}
TFilter_conjunction::TFilter_conjunction(PFilterList af)
: filters(af)
{}
bool TFilter_conjunction::operator()(const TExample &ex)
{
if (filters)
PITERATE(TFilterList, fi, filters)
if (!(*fi)->call(ex))
return negate;
return !negate;
}
TFilter_disjunction::TFilter_disjunction()
: filters(mlnew TFilterList())
{}
TFilter_disjunction::TFilter_disjunction(PFilterList af)
: filters(af)
{}
bool TFilter_disjunction::operator()(const TExample &ex)
{
if (filters)
PITERATE(TFilterList, fi, filters)
if ((*fi)->call(ex))
return !negate;
return negate;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -