В QHash при использовании erase() помимо удаления нужного объекта затираются данные у соседнего
Имеется QHash<int, Examiner>, данный хэш заполняется элементами, затем по нему рисуется табличка QTableWidget. Задача: по указанному пользователем номеру ряда в таблице удалить соответствующую запись из хэша и из таблицы. Проблема: по указанному ряду я получаю объект класса Examiner, затем ищу Key, соответствующий этому элементу в QHash, и удаляю с помощью erase(). Почему-то помимо удаления нужной пары ключ-значение в хэше еще у одного объекта класса Examiner затираются данные (т.е., например, строковые значения меняются на ""). При использовании remove() результат аналогичный.
Почему так происходит и как сделать так, чтобы просто удалялась нужная пара ключ-значение, а остальные не менялись?
Часть кода, где заполняется таблица и удаляется нужная пара ключ-значение:
QHash<int, Examiner> examiners;
examiners.insert(identificator++, Examiner(1, "Shevchenko", "Anna", "Igorevna", "916836493", "[email protected]"));
examiners.insert(identificator++, Examiner(2, "Potapov", "Oleg", "Stepanovich", "9163789423", "[email protected]"));
examiners.insert(identificator++, Examiner(3, "Ivanova", "Inna", "Pavlovna", "9269217654", "[email protected]"));
examiners.insert(identificator++, Examiner(4, "Zaytcev", "Ilya", "", "9256134981", "[email protected]"));
ui->tableWidget->setRowCount(examiners.size());
ui->tableWidget->setColumnCount(6);
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "id" << "surname" << "name" << "patronymic" << "phone" << "email");
for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
for (int j = 0; j < ui->tableWidget->columnCount(); j++) {
switch (j) {
case 0: {
QTableWidgetItem *tbl = new QTableWidgetItem(QString::number(examiners.value(i).getId()));
ui->tableWidget->setItem(i,j,tbl);
break;
}
case 1: {
QTableWidgetItem *tbl = new QTableWidgetItem(examiners.value(i).getSurname());
ui->tableWidget->setItem(i,j,tbl);
break;
}
case 2: {
QTableWidgetItem *tbl = new QTableWidgetItem(examiners.value(i).getName());
ui->tableWidget->setItem(i,j,tbl);
break;
}
case 3: {
QTableWidgetItem *tbl = new QTableWidgetItem(examiners.value(i).getPatronymic());
ui->tableWidget->setItem(i,j,tbl);
break;
}
case 4: {
QTableWidgetItem *tbl = new QTableWidgetItem(examiners.value(i).getPhone());
ui->tableWidget->setItem(i,j,tbl);
break;
}
case 5: {
QTableWidgetItem *tbl = new QTableWidgetItem(examiners.value(i).getEmail());
ui->tableWidget->setItem(i,j,tbl);
break;
}
default:
break;
}
}
}
int row = 2;
Examiner ex;
for (int i = 0; i < ui->tableWidget->columnCount(); i++) {
switch (i) {
case 0: {
QTableWidgetItem *tbl = ui->tableWidget->item(row,i);
ex.setId(tbl->text().toInt());
break;
}
case 1: {
QTableWidgetItem *tbl = ui->tableWidget->item(row,i);
ex.setSurname(tbl->text());
break;
}
case 2: {
QTableWidgetItem *tbl = ui->tableWidget->item(row,i);
ex.setName(tbl->text());
break;
}
case 3: {
QTableWidgetItem *tbl = ui->tableWidget->item(row,i);
ex.setPatronymic(tbl->text());
break;
}
case 4: {
QTableWidgetItem *tbl = ui->tableWidget->item(row,i);
ex.setPhone(tbl->text());
break;
}
case 5: {
QTableWidgetItem *tbl = ui->tableWidget->item(row,i);
ex.setEmail(tbl->text());
break;
}
default: {
break;
}
}
}
qDebug() << "Размер хеша до удаления: " << examiners.size();
qDebug() << "Данные до удаления:";
for (int i = 0; i < examiners.size(); i++) {
qDebug() << examiners.value(i).getName() << " " << examiners.value(i).getSurname();
}
QHash<int, Examiner>::iterator i = examiners.find(examiners.key(ex));
while (i != examiners.end() && i.key() == examiners.key(ex)) {
qDebug() << "Имя удаляемого объекта: " << i.value().getName();
i = examiners.erase(i);
}
//qDebug() << examiners.remove(examiners.key(ex));
ui->tableWidget->removeRow(row);
qDebug() << "Размер хеша после удаления: " << examiners.size();
qDebug() << "Данные после удаления:";
for (int i = 0; i < examiners.size(); i++) {
qDebug() << examiners.value(i).getName() << " " << examiners.value(i).getSurname();
}
Вывод в консоли:
Размер хеша до удаления: 4
Данные до удаления:
"Anna" "Shevchenko"
"Oleg" "Potapov"
"Inna" "Ivanova"
"Ilya" "Zaytcev"
Имя удаляемого объекта: "Inna"
Размер хеша после удаления: 3
Данные после удаления:
"Anna" "Shevchenko"
"Oleg" "Potapov"
"" ""
Заголовочный файл класса Examiner:
#include <QString>
#ifndef EXAMINER_H
#define EXAMINER_H
class Examiner
{
friend QDataStream& operator>>(QDataStream& out, Examiner& examiner);
private:
int id;
QString surname;
QString name;
QString patronymic;
QString phone;
QString email;
public:
Examiner(): id(0), surname(""), name(""), patronymic(""), phone(""), email("") { };
Examiner(int id, QString surname, QString name, QString patronymic, QString phone, QString email)
{
this->id = id;
this->surname = surname;
this->name = name;
this->patronymic = patronymic;
this->phone = phone;
this->email = email;
}
int getId() {
return this->id;
}
QString getSurname() {
return this->surname;
}
QString getName() {
return this->name;
}
QString getPatronymic() {
return this->patronymic;
}
QString getPhone() {
return this->phone;
}
QString getEmail() {
return this->email;
}
void setId(int id) {
this->id = id;
}
void setSurname(QString s) {
this->surname = s;
}
void setName(QString n) {
this->name = n;
}
void setPatronymic(QString p) {
this->patronymic = p;
}
void setPhone(QString ph) {
this->phone = ph;
}
void setEmail(QString e) {
this->email = e;
}
friend bool operator== (const Examiner& ex1, const Examiner& ex2) {
return (ex1.id == ex2.id && ex1.surname == ex2.surname && ex1.name == ex2.name && ex1.patronymic == ex2.patronymic
&& ex1.phone == ex2.phone && ex1.email == ex2.email);
}
};
#endif // EXAMINER_H
Ответы (1 шт):
У вас не затираются другие данные, вы просто не то выводите. QHash это ассоциативная таблица "ключ-значение", когда вы делаете insert, вы вставляете пары таких значений. Inna Ivanova, которую вы удаляете, идет в хеше под ключом 2, судя по всему. После удаления ключи у вас становятся 0, 1, 3 (2 вы удалили). Длина таблицы 3, поэтому вы запрашиваете данные по ключам 0, 1, 2. 2 у вас удаленный, а до 3 вы не добрались, поэтому он у вас не выводится.
По ассоциативным массивам итерируются не так, как вы, а примерно вот так:
for (auto i = examiners.begin(); i != examiners.end(); ++i)
qDebug() << i.key() << i.value().getName();
Также надо заметить, что у вас теряется смысл использования ассоциативного массива, потому что вы все равно делаете поиск по значению. В такой ситуации проще использовать вектор, или же сделать ключом что-то, по чему вы можете сделать быстрый поиск, например у вас фигурирует id, который обычно хорошо подходит на роль ключа.