Безопасно ли изменять std :: pair <U, V> :: first в векторе пар? - PullRequest
1 голос
/ 01 декабря 2008

В настоящее время я работаю над классом базы данных ДНК, и в настоящее время я связываю каждую строку в базе данных как со счетом совпадения (на основе расстояния редактирования), так и с фактической самой последовательностью ДНК, безопасно ли сначала изменять таким образом в пределах цикл итерации?

typedef std::pair<int, DnaDatabaseRow> DnaPairT;
typedef std::vector<DnaPairT>          DnaDatabaseT;

// ....

for(DnaDatabaseT::iterator it = database.begin();
    it != database.end(); it++)
{
    int score = it->second.query(query);
    it->first = score;
}

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

Ответы [ 2 ]

5 голосов
/ 01 декабря 2008

Чтобы ответить на ваш первый вопрос, да. Совершенно безопасно изменять членов вашей пары, поскольку фактические данные в паре не влияют на сам вектор.

edit: У меня такое ощущение, что вы получили ошибку при использовании карты, потому что вы пытались изменить значение first внутренней пары карты. Это недопустимо, потому что это значение является частью внутренней работы карты.

Как указано dribeas :

На картах вы не можете сначала изменить, так как это нарушит инвариант карты, являющейся отсортированным сбалансированным деревом

edit: Чтобы ответить на ваш второй вопрос, я не вижу ничего плохого в том, как вы структурируете данные, но я бы хотел, чтобы база данных содержала указателей на DnaPairT объекты, а не сами объекты. Это значительно уменьшит объем памяти, который копируется во время процедуры сортировки.

#include <vector>
#include <utility>
#include <algorithm> 

typedef std::pair<int, DnaDatabaseRow> DnaPairT;
typedef std::vector<DnaPairT *>       DnaDatabaseT;

// ...

// your scoring code, modified to use pointers
void calculateScoresForQuery(DnaDatabaseT& database, queryT& query)
{
    for(DnaDatabaseT::iterator it = database.begin(); it != database.end(); it++)
    {
        int score = (*it)->second.query(query);
        (*it)->first = score;
    }
}

// custom sorting function to handle DnaPairT pointers
bool sortByScore(DnaPairT * A, DnaPairT * B) { return (A->first < B->first); }

// function to sort the database
void sortDatabaseByScore(DnaDatabaseT& database)
{
    sort(database.begin(), database.end(), sortByScore);
}

// main
int main()
{
    DnaDatabaseT database;

    // code to load the database with DnaPairT pointers ...

    calculateScoresForQuery(database, query);
    sortDatabaseByScore(database);

    // code that uses the sorted database ...
}

Единственная причина, по которой вам может потребоваться поиск более эффективных методов, заключается в том, что ваша база данных настолько огромна, что цикл сортировки занимает слишком много времени. Если бы это было так, я бы предположил, что ваша функция query будет занимать большую часть времени обработки.

1 голос
/ 01 декабря 2008

Вы не можете изменить, так как переменная first из std :: pair определена const

...