tags:

views:

87

answers:

3

I have a struct viz:

struct NameKey
{
    std::string      fullName;
    std::string      probeName;
    std::string      format;
    std::string      source;
}

which are held in a QList:

QList<NameKey> keyList;

what I need to do is find an occurence in keyList of a partial match where the search is for a NameKey that only has two members filled. All the keyList entries are full NameKey's.

My current implementation is , well, boring in the extreme with too many if's and conditions.

So, If I have a DataKey with a fullName and a format I need to find all the occurences in keyList which match. Any useful Qt/boost things available?

+3  A: 

Just a note: any solution that uses a list has O(n) time complexity, at least.

One option is to use QString, instead of std::string, and take advantage of their regular expressions built-in support.

Example:

#include <QList>
#include <QString>
#include <QRegExp>

struct NameKey
{
    QString    fullName;
    QString    probeName;
    QString    format;
    QString    source;
};

QList<NameKey>  keyList; // <--

void Foo() {
   QRegExp  reg("pattern"); // <-- prepare a regular expression (format)
   NameKey  nk;
   foreach (nk, keyList) {
      if (nk.fullName.contains(reg)) {
         // a match ...
         break;
      }
      // ...
   }
}
Nick D
@Nick D: You might want to clarify that any solution to THIS problem using a list will have O(n) time complexity at least. In other cases this is not true.
Adam W
@Adam, if we store the NameKey records in a list container, we have no option except from iterating over that list while we search for matches. Unless we use an auxiliary container, ie a Map or Trie, to store extra info to speed up the search I don't see a faster way to implement it. Did I miss something?
Nick D
@Nick D: One example is if your list is sorted you can use a binary search and get O(log n). Or like you said, if there is an index structure to speed up the search.
Adam W
@Adam, binary search a sorted vector. Sure we can do something like that. Of course we'll have to keep the order when we add new records.
Nick D
@Nick D: I understand that, I was just pointing out that "any solution that uses a list has O(n) time complexity, at least" assumes conditions (an unsorted list for example).
Adam W
@Adam, but we cannot actually binary search a list data structure unless it's implemented as a vector, and we can't assume that a priori.
Nick D
@Nick D: http://doc.qt.nokia.com/4.6/containers.html#algorithmic-complexity if it is a `QList` (as it is in this case) you can. A `QLinkedList` would cause problems.
Adam W
@Adam, exactly what I said in my comment. QList *hides* a vector in its core. Thanks for pointing that out, I'm new to Qt framework and I still explore it :-)
Nick D
@Nick D: I'm glad we can argue the same point so well! :)
Adam W
@Adam, BTW Qt rocks!
Nick D
@Nick D: Oh I know, I don't think I would ever want to do C++ again without it.
Adam W
Ah, I wish. I can'r change the struct regretfully.
ExpatEgghead
Doesn't boost have a regex now?
ExpatEgghead
A: 

Similar to Nick D's answer:

#include <QList>
#include <QString>
#include <QRegExp>

struct NameKey
{
    QString    fullName;
    QString    probeName;
    QString    format;
    QString    source;

    bool containsPattern(const QRegExp &pattern) {
       return fullName.contains(reg) ||
              probeName.contains(reg) ||
              format.contains(reg) ||
              source.contains(reg);
    }
};

QList<NameKey> matches(const QList<NameKey> &keyList, const QString &pattern) {
   QRegExp  reg(pattern);
   QList<NameKey> matches;
   foreach (NameKey nk, keyList) {
      if (nk.containsPattern(reg))
         matches << nk;
   }
   return matches;
}

There are obviously many ways to do this. I like to put as much intelligence into data structures as possible.

Adam W
Annoyingly I can't change NameKey.
ExpatEgghead
+2  A: 

QList is compatible with STL. So you can use it with STL algorithm:

struct NameKeyMatch {
    NameKeyMatch(const std::string & s1, const std::string & s2, const std::string & s3, const std::string & s4)
    : fullName(s1), probeName(s2), format(s3), source(s4) {}

    bool operator()(const NameKey & x) const
    {
        return  fullName.size() && x.fullName == fullName &&
                probeName.size && x.probeName == probeName &&
                format.size && x.format == format &&
                source.size && x.source == source;
    }

    std::string fullName;
    std::string probeName;
    std::string format;
    std::string source;
};

QList<int>::iterator i = std::find_if(keyList.begin(), keyList.end(), NameKeyMatch("Full Name", "", "Format", ""));

I don't know if Qt will actively maintain STL compatibility though.

Stephen Chu
Well this looks cool! Thanks.
ExpatEgghead
mine looks a little different. return !(fullName.size()
ExpatEgghead