Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Qt и кроссплатформенное программирование С/С++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.02.2011, 00:58   #1
Dayman
Форумчанин
 
Аватар для Dayman
 
Регистрация: 12.01.2011
Сообщений: 186
По умолчанию [Qt] QList и indexOf

Допустим есть класс с двумя полями
Код:
class someclass{
private:
quint32 ID; QString name;
public:
bool operator==(const someclass& other) const;
}
Пачка объектов этого класса помещается в QList.
Требуется организовать поиск в QList как по ID так и по name.
QList::indexOf, как я понял, подходит только для поиска по одному полю.

Есть ли какой хитрый способ все это организовать (полей естественно может быть не два) или по-старинке искать перебором вручную?
Lingua c++ non penis caninus est.
Dayman вне форума Ответить с цитированием
Старый 14.02.2011, 03:43   #2
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Ничего хитрого.
Код:
class SomeClass
{
private:
    quint32 m_id;
    QString m_name;
    static bool m_MUST_COMPARE_BY_NAME;
public:
    SomeClass(quint32 id, const QString &name): m_id(id), m_name(name) {}
    bool operator== (const SomeClass &other) const {
        if (m_MUST_COMPARE_BY_NAME) {
            return other.m_name == m_name;
        } else {
            return other.m_id == m_id;
        }
    }
    static void setCompareByName(bool b) { m_MUST_COMPARE_BY_NAME = b; }
};
Чтобы минимизировать вероятность твоей ошибки, можешь сделать такую обёртку:
Код:
class SomeClassList: public QList<SomeClass>
{
public:
    int indexOfByName(const SomeClass &value, int from = 0) const {
        SomeClass::setCompareByName(true);
        return QList::indexOf(value);
    }
    int indexOfById(const SomeClass &value, int from = 0) const {
        SomeClass::setCompareByName(false);
        return QList::indexOf(value);
    }
private:
    /// Приватный indexOf, который нельзя вызывать.
    int indexOf(const SomeClass &value, int from = 0) const {
        QASSERT(false);
    }
}'
Как-то так...

Можно сделать конструктор у SomeClass приватным и разрешить им пользоваться только классу SomeClassList:
Код:
class SomeClass
{
    friend class SomeClassList;
private:
    quint32 m_id;
    QString m_name;
    static bool m_MUST_COMPARE_BY_NAME;
    SomeClass(quint32 id, const QString &name): m_id(id), m_name(name) {}
public:
    bool operator== (const SomeClass &other) const {
        if (m_MUST_COMPARE_BY_NAME) {
            return other.m_name == m_name;
        } else {
            return other.m_id == m_id;
        }
    }
};
Код:
class SomeClassList: public QList<SomeClass>
{
public:
    void addItem(quint32 id, const QString &name) {
        push_back(SomeClass(id, name));
    }
    int indexOfByName(const SomeClass &value, int from = 0) const {
        SomeClass::setCompareByName(true);
        return QList::indexOf(value);
    }
    int indexOfById(const SomeClass &value, int from = 0) const {
        SomeClass::setCompareByName(false);
        return QList::indexOf(value);
    }
private:
    /// Приватный indexOf, который нельзя вызывать.
    int indexOf(const SomeClass &value, int from = 0) const {
        QASSERT(false);
    }
};
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su

Последний раз редактировалось Obey-Kun; 14.02.2011 в 04:03.
Obey-Kun вне форума Ответить с цитированием
Старый 14.02.2011, 03:46   #3
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Хотя лично мне такая идея не по нраву совсем, грязко и гадко. Лучше сделать SomeClassList с методами indexOfByName(const QString &name, int from = 0) const и аналогичным для ID, а их сделать по аналогии с indexOf в Qt: http://qt.gitorious.org/qt/qt/blobs/...list.h#line825
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su

Последний раз редактировалось Obey-Kun; 14.02.2011 в 04:11.
Obey-Kun вне форума Ответить с цитированием
Старый 14.02.2011, 16:48   #4
Dayman
Форумчанин
 
Аватар для Dayman
 
Регистрация: 12.01.2011
Сообщений: 186
По умолчанию

Интересно. Про наследование от QList я как-то не подумал.
Тогда быть может лучше перегрузить операторы сравнения:
Код:
bool operator==(quin32 ID) const;
bool operator==(QString& other) const;
И вызывать их из indexOfByXYZ.
Правда работать будет только в пределах разных типов. Если надо будет искать по двум QString полям (скажем name и description), то без статического поля не обойтись.

Edit: Пфф, совсем забыл, что из indexOfXYZ вызывается стандартный indexOf, значит только статические поля.
Lingua c++ non penis caninus est.
Dayman вне форума Ответить с цитированием
Старый 14.02.2011, 17:11   #5
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Лучше просто унаследуй QList и сделай там 2 метода по аналогии с http://qt.gitorious.org/qt/qt/blobs/...list.h#line825
А то со статическим полем решением грязное какое-то
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su
Obey-Kun вне форума Ответить с цитированием
Старый 14.02.2011, 17:32   #6
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

А ещё красивей сделать как в сшарпе — научить* один раз QList работать с интерфейсом IComparer и пописывать себе компараторы по мере необходимости:

Код:
class Wish
{
    public string Name;
    public int Priority;

    public Wish (string name, int priority) {
        Name = name;
        Priority = priority;
    }
}

class PriorityComparer: Comparer <Wish>
{
    public override int Compare (Wish x, Wish y) {
        if (object.Equals (x, y)) return 0; // Fail-safe check
        return x.Priority.CompareTo (y.Priority);
  }
}

var wishList = new List<Wish>();
wishList.Add (new Wish ("Peace", 2));
wishList.Add (new Wish ("Wealth", 3));
wishList.Add (new Wish ("Love", 2));
wishList.Add (new Wish ("3 more wishes", 1));
wishList.Sort (new PriorityComparer());
foreach (Wish w in wishList) Console.Write (w.Name + " | ");

// OUTPUT: 3 more wishes | Love | Peace | Wealth |
Тут пример с Sort, но идея, дума понятна.

(* научить — т.е. создать свой класс, наследованный от).
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."

Последний раз редактировалось veniside; 14.02.2011 в 17:36.
veniside вне форума Ответить с цитированием
Старый 14.02.2011, 17:35   #7
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Компараторы и в плюсах можно делать, обычные указатели на функции.
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su

Последний раз редактировалось Obey-Kun; 14.02.2011 в 17:41.
Obey-Kun вне форума Ответить с цитированием
Старый 14.02.2011, 17:38   #8
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Вот и прекрасно, что можно, я и не сомневался. Осталось скрестить их с QList и будет красивое решение.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 14.02.2011, 17:44   #9
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

тогда уж можно сделать просто шаблонный indexOf, а он тупо будет использовать соответствующий operator==, и никаких компараторов не надо.
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su
Obey-Kun вне форума Ответить с цитированием
Старый 14.02.2011, 17:58   #10
Dayman
Форумчанин
 
Аватар для Dayman
 
Регистрация: 12.01.2011
Сообщений: 186
По умолчанию

Цитата:
Сообщение от Obey-Kun Посмотреть сообщение
тогда уж можно сделать просто шаблонный indexOf, а он тупо будет использовать соответствующий operator==, и никаких компараторов не надо.
Тогда придется внутри indexOf перебирать вручную.
Lingua c++ non penis caninus est.
Dayman вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
indexOf Progsenya JavaScript, Ajax 2 05.12.2010 12:29
memo и IndexOf grafgrial Общие вопросы Delphi 4 12.08.2010 07:16
IndexOf Cpluser Microsoft Office Excel 0 17.05.2010 18:11
Indexof Cpluser Microsoft Office Excel 1 09.04.2010 04:52
Не применяется параметр Options для Table1.IndexDefs.IndexOf[i] adriano БД в Delphi 8 04.03.2009 18:07