3

I am performing a sort on the following collection of strings using QString::localeAwareCompare:

Search term used: "Mountain"

Results:

  • Goblin Mountaineer
  • Madblind Mountain
  • Magnetic Mountain
  • Mountain
  • Mountain Goat
  • Mountain Stronghold
  • Mountain Titan
  • Mountain Valley
  • Mountain Yeti
  • Snow-Covered Mountain
  • The Lady of the Mountain

The order is sorted lexically according to QString::compare. Ultimately I would like the order to have the following rules:

  1. Exact match at top
  2. Exact match with preceding values sorted lexically.
  3. Match contained in word sorted lexically

    • Mountain (1)
    • Mountain Goat (2)
    • Mountain Stronghold (2)
    • Mountain Titan (2)
    • Mountain Valley (2)
    • Mountain Yeti (2)
    • Goblin Mountaineer (3)
    • Madblind Mountain (3)
    • Magnetic Mountain (3)
    • Snow-Covered Mountain (3)
    • The Lady of the Mountain (3)

Does anyone know how this might be achieved? I am able to implement a custom sort of some kind.

EDIT:

Here is some janky code I have tried to get exact matches to the top, which works.

bool CardDatabaseDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const {

    QString leftString = sourceModel()->data(left).toString();
    QString rightString = sourceModel()->data(right).toString();

    if (leftString.compare(cardName, Qt::CaseInsensitive) == 0) {// exact match should be at top
        return true;
    }

    if (rightString.compare(cardName, Qt::CaseInsensitive) == 0) {// exact match should be at top
        return false;
    }

    return QString::localeAwareCompare(leftString, rightString) < 0;

}
2
  • show what you have tried Commented Mar 3, 2015 at 11:37
  • @ArunA.S added something that I have tried as an experiment. Commented Mar 3, 2015 at 11:40

1 Answer 1

2

Here is a way you could complete your current code. It tries to sort from the most special to the most general case: exact match, match-plus-stuff, everything else.

bool CardDatabaseDisplayModel::lessThan(const QModelIndex &left, 
                               const QModelIndex &right) const {

    QString leftString = sourceModel()->data(left).toString();
    QString rightString = sourceModel()->data(right).toString();

    // The exact match (if any) should be at the top
    if (leftString.compare(cardName, Qt::CaseInsensitive) == 0)
        return true;
    if (rightString.compare(cardName, Qt::CaseInsensitive) == 0)
        return false;

    // We know that neither is the perfect match. 
    // But is either a match-plus-some-stuff ?
    bool isLeftType2 = leftString.startsWith(cardName, Qt::CaseInsensitive);
    bool isRightType2 = rightString.startsWith(cardName, Qt::CaseInsensitive);
    if (isLeftType2 && !isRightType2)
        return true;
    if (isRigthType2 && !isLeftType2)
        return false;

    // At this point we're sorting two matches of the same type
    // Either both are matches-plus-some-stuff or partial matches
    return QString::localeAwareCompare(leftString, rightString) < 0;
}

I assumed that something like "Mountaineer" alone would be type 2 and not type 3, you could add a +" " in the comparisons if you don't want that.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.