2012-01-29 4 views
2

У меня есть два классаКак SQL выбрать обычно реализуется

class PopulationMember 
{ 
public: 
    void operationOnThisMember1(); 
    void operationOnThisMember2(); 
    ... 

private: 

    Population* populaltion_; 
} 

class Population 
{ 
public: 
    void operationOnAllMembers1(); 
    void operationOnAllMembers2(); 
    ... 
    void operationOnAllMembers100(); 

    void sortAllMembersCriterium1(); 
    void sortAllMembersCriterium2(); 
    ... 
    void sortAllMembersCriterium100(); 

private: 
    QVector<PopulationMember*> members_; 
} 

Я хотел бы реализовать ВЫБРАТЬ подобную функциональность моей структуры. Это может выполнять операции только для тех членов, которые имеют определенную комбинацию свойств.

До сих пор я думал, что два подхода:

  1. Реализовать метод, который будет возвращать новый объект Population, состоящий из членов, которые удовлетворяют определенное условие.

    Popuation Popuation::select(bool (predicate*) (PopulationMember*)); 
    
  2. Добавить флаг

    bool selected_; 
    

    каждому PopulationMember.

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

Есть ли третий, лучший способ?

+5

'SELECT' не для фильтрации, он предназначен для проецирования. – jason

+0

Пожалуйста, что вы имеете в виду, спроектировав? Я хотел бы реализовать функциональность фильтрации. –

+2

Проектирование в основном преобразует структуру A в структуру B (где A и B могут быть одной и той же структуры, но часто это не так). Например, «SELECT» таблица «FROM» для исключения всех остальных столбцов. Синтаксис SQL 'SELECT' всегда требует проекции; 'SELECT * FROM" table "означает концептуально проекцию, которая не имеет чистого эффекта. Фильтрация - это 'WHERE' часть SQL-запроса. – hvd

ответ

2

Подход, который я хотел бы сделать, - открыть интерфейс итератора для всей коллекции. Чтобы реализовать какой-то выбор, я использовал бы итератор-адаптеры, например. один из которых принимает унарный предикат, который обеспечивает новый вид диапазона. Таким образом, нет никакого влияния на сохраненный объект или накладные расходы при создании отдельной коллекции. Если вы посмотрите на адаптеры итератора Boost, вы, возможно, уже получите то, что нужно.

1

Я никогда не смотрел, но я ожидаю, что это будет метод 1. См. MySQL source code, чтобы подтвердить мое ожидание. :-)

1

Это предложение, основанное на чем-то подобном, которое я должен был сделать один раз, что является расширенной формой вашего первого подхода. Преимуществом является использование концепций STL и свобода либо реализовать множество функторов, либо несколько параметризуемых функторов.

class All 
{ 
public: 
    bool operator()(const PopulationMember* entity) const 
    { 
     return true; 
    } 
}; 

class AscByID 
{ 
public: 
    bool operator()(const PopulationMember* a, const PopulationMember* b) const 
    { 
     return a->getId() < b.getId(); 
    } 
}; 

template<typename Entity, class Predicate, class SortComparator> 
class Query 
{ 
public: 
    typedef std::set<Entity, SortComparator> ResultSet; 

    Query(const Predicate& predicate = Predicate(), const SortComparator& cmp = SortComparator()) : 
      predicate(predicate), resultSet(cmp) 
    { 
    } 

    bool operator()(const Entity& entity) 
    { 
     if (predicate(entity)) 
     { 
      resultSet.insert(entity); 
      return true; 
     } 
     return false; 
    } 

    const ResultSet& getResult(void) const 
    { 
     return resultSet; 
    } 

    void clearResult(void) 
    { 
     resultSet.clear(); 
    } 
private: 
    Predicate predicate; 
    ResultSet resultSet; 
}; 

int main() 
{ 
    Query<const PopulationMember*, All, AscByID> query; 

    Popuation::execute(query); 
    //do something with the result 
    query.getResult(); 
    //clear the result 
    query.clearResult(); 
    //query again 
    Popuation::execute(query); 
    //do something useful again 
    return 0; 
} 
Смежные вопросы