Извлекать данные из файла в векторы, но избегать дубликатов

Я хочу читать данные в файлах, которые отформатированы как:

Point1, [3, 4]

Я использую разделители ‘[‘ ‘]’ и ‘,’ и заменяю их на » (пустое место). Мой код сейчас в порядке и работает. Но проблема в том, если Point1, [3, 4] появился один раз, я хочу, чтобы он был уникальным и не появлялся снова, если существуют те же данные в текстовом файле.

Вот что у меня есть:

string line, name;
char filename[50];
int x,y;

cout << "Please enter filename : ";
cin >> filename;

ifstream myfile(filename);
if (myfile.is_open()) {
while ( myfile.good() ) {
getline(myfile, line);

for (unsigned int i = 0; i < line.size(); ++i) {
if (line[i] == '[' || line[i] == ']' || line[i] == ',') {
line[i] = ' ';
}
istringstream in(line);
in >> name >> x >> y;
}
cout <<name <<endl;

if (name=="Point") {
p.push_back(Point(x,y));
}
count++;
}
myfile.close();
cout << count;
}
else cout<< "Unable to open file";

Как мне это сделать? Я попытался добавить это после if(name=="Point")

for (int j=0; j<p.size(); j++) {
if(p.getX != x && p.getY) != y) {
p.push_back(Point(x,y))
}
}

…но это не работает должным образом, так как данные не были сохранены в векторе.

Кто-нибудь может помочь?

0

Решение

Вместо хранения ваших данных в vectors Вы можете сохранить его в sets, Набор содержит только уникальные значения, поэтому вам не нужно проверять уникальность вашего Points, set справится с этим.

Вместо определения vector<Point>, вы должны определить set<Point>и вместо того, чтобы использовать p.push_back чтобы добавить точки в ваш вектор, вы должны использовать p.insert если это set,

Вы можете проверить set документация Вот.

4

Другие решения

Предполагая, что вы хотите сохранить свое хранилище данных в std::vector<Point> Вы можете просто проверить, что соответствующая точка уже не существует. Предполагая, что определен оператор равенства, это так просто:

if (p.end() == std::find(p.begin(), p.end(), Point(x, y))) {
p.push_back(Point(x, y));
}

если ты Point Тип не имеет оператора равенства и не должен его получать, вы можете использовать объект функции вместе с find_if() вместо этого, например:

if (p.end() == std::find_if(p.begin(), p.end(),
[=](Point const& v) { return x == v.x && y == v.y; })) {
...

Вы должны отделить свои циклы от других операций: цикл, который вы предлагаете проверить, существует ли точка, в принципе std::find() делает, кроме того, что вы вставляете новую точку в каждой итерации! Сначала вы хотите просмотреть все существующие точки и посмотреть, существует ли он где-либо. Только если этого не произойдет, вы добавите новую точку.

Обратите внимание, что вы сделали аналогичную ошибку при замене символов в вашей строке: вы пытаетесь декодировать строку после проверки каждого символа. Это не столько семантическая проблема, но серьезная проблема с производительностью. Вы должны заменить символы в цикле и после этот цикл вы должны декодировать строку только один раз. Конечно, при декодировании строки необходимо проверить, был ли формат в порядке, как есть всегда необходимо определить, была ли операция ввода успешной. То есть после замены вашего цикла символов вы хотите что-то вроде:

std::istringstream in(line);
if (in >> name >> x >> y) {
// now process the data
}

… или, если вы похожи на меня и не любите называть вещи, которые только временно присутствуют:

if (std::istringstream(line) >> std::ws >> name >> x >> y) {

Как еще одно примечание: проверка потока для good() как правило, это неправильно, потому что поток может быть в совершенно хороших условиях, за исключением того, что он видел EOF в какой-то момент и, таким образом, как установлено std::ios_base::eofbit, Что еще более важно, вы должны проверить после операция ввода, не раньше! То есть ваш первый цикл должен начинаться примерно так:

while (std::getline(myFile, line)) {
...
0

По вопросам рекламы [email protected]