Search code examples
c++qttableviewviewmodel

instead of so many if statements I want a logic where I can do it with one statement or optimized way


I have a vector of structures vector<S> sData which my structure contains 5 elements (name, age, techs, projects, language)

The user can input name and it should output the structures that equal to that name and for the other elements too.

My problem is that the user can input two of them only and it should only check for those like user can input age and language it should output the list of people who have the same age and language. If you imagine you can write so many if statements so it will give a right output because you have 5 elements, and the user can choose 5 of them 4 and randomly he can input 3 or 4 of them and my program should understand that logic.

In my code I'm writing with Qt widget application. When the user didn't enter any of the strings(name, techs, projects, rate), the default value is NULL and the age is -1.

struct S
{
    QString name;
    int age;
    QString techs;
    QString projects;
    QString rate;

};

QVector<S> sData;
QVector<int> indexData;





//this is how i did for the name
 indexData.clear();
 if(searchName!=NULL)//i don't want to write this if for name and age ||
 // name and tech ... then age and tech etc.
 {
    for(int i=0;i<sData.count();++i)
    {
        if(searchName==sData[i].name)
        {   
         indexData.push_back(i);   
        }
    }
 }

Solution

  • I'd suggest a little code refactor. Let's consider adding a helper structure SearchS which holds all params you are looking for (and comparison operator):

    struct S {
      QString name;
      int age = -1;
      QString techs;
      QString projects;
      QString rate;
    };
    
    struct SearchS {
      std::optional<QString> name;
      std::optional<int> age;
      std::optional<QString> techs;
      std::optional<QString> projects;
      std::optional<QString> rate;
      static bool string_match(const QString& s, const std::optional<QString>& search_s) {
        return !search_s || *search_s == s;
      }
      bool operator==(const S& s) const noexcept {
        return string_match(s.name, name) &&
            string_match(s.techs, techs) &&
            string_match(s.projects, projects) &&
            string_match(s.rate, rate) &&
            (!age || *age == s.age);
      }
    };
    

    This allows you to iterate over data vector and filter results. The cleanest way to do this I think is using ranges-v3:

    std::vector<S> sData;
    SearchS target;
    target.name = "John";
    target.age = 28;
    // ... other params if needed ...
    
    auto filtered_items = data | ranges::views::filter([&target](const auto& item) {
      return target == item;
    });
    

    Here you can apply other filters... Or iterate over the filtered results:

    for(auto&& item : filtered_items) {
      // ... add your code here ...
    }