如何按顺序删除向量中的重复值

How can I delete repetitive values in vector with order?

本文关键字:向量 何按 顺序 删除      更新时间:2023-10-16

我有一个包含3列的txt文件:"dd/mm/yyyy HH:MM:SS number(000.000)"。大约有368个条目。

我想选择strings,其中第三列的值是唯一的(第一次见面)。秩序很重要。

在我的代码中,我在vector(dtp)中读取文件,然后在vector(datatimepressure)中填充每个column。然后我从第三列中删除值并得到这个。

我的问题是,如何将第一列和第二列与正确的索引相加,得到这个?

数据示例(前15个值):

26.07.2017  15:47:38    82.431 
26.07.2017  16:47:46    83.431
26.07.2017  17:47:54    85.431
26.07.2017  18:48:02    84.431
26.07.2017  19:48:09    83.431
26.07.2017  20:48:17    83.431
26.07.2017  21:48:24    84.431
26.07.2017  22:48:32    83.431
26.07.2017  23:48:40    83.431
27.07.2017  00:48:48    84.431
27.07.2017  01:48:55    84.431
27.07.2017  02:49:03    84.431
27.07.2017  03:49:10    84.431
27.07.2017  04:49:19    84.431
27.07.2017  05:49:27    86.431

代码:

include <iostream> 
include <fstream> 
include <string> 
include <algorithm> 
include <iterator> 
include <sstream> 
include <vector> 
include <cstring> 
include <ctime>
using namespace std;
int main()
{
const clock_t start = clock(); 
system("mode con cols=50 lines=1000"); 
setlocale(LC_ALL, "Russian"); 
vector<string> dtp; 
vector<string> data;
vector<string> time;
vector<double> pressure;
double num(0.0); 
string line, tmp1, tmp2; 
int len = 368;
int f, i, j, k;
ifstream file("data.txt"); 
while (!getline(file, line).eof()) 
dtp.push_back(line); 
for (string &it : dtp) 
{ 
{
istringstream isstr(it);
isstr >> tmp1;
data.push_back(tmp1);
}
{
istringstream isstr(it);
isstr >> tmp1 >> tmp2;
time.push_back(tmp2);
}
{
istringstream isstr(it);
isstr >> tmp1 >> tmp2 >> num;
pressure.push_back(num);
}
}
f = 0;
for (i = 0; i < len; i++) 
{
for (j = i + 1; j < len; j++) 
{
if (pressure[i] == pressure[j]) 
{
for (k = j; k < (len - 1); k++)
pressure[k] = pressure[k + 1];
len--;
j--;
f = 1;
}
}
}
if (f == 1)
{
for (i = 0; i < len; i++)
cout << pressure[i] << endl;
}
const double vremya = static_cast<double>(clock() - start) / CLOCKS_PER_SEC; 
cout << "Time is: " << vremya << " seconds" << endl; 
system("pause");
return 0;
}

我认为您最好将其视为一个包含两列的表:

Timestamp Pressure

然后用它来代替。使用时间戳有助于使用日期/时间库,该库可以解析、格式化和排序时间戳。

这是它可能的样子。代码下方的详细说明:

#include "date/date.h"
#include <algorithm>
#include <iostream>
#include <sstream>
#include <utility>
#include <vector>
std::istringstream file
{
"26.07.2017  15:47:38    82.431n"
"26.07.2017  16:47:46    83.431n"
"26.07.2017  17:47:54    85.431n"
"26.07.2017  18:48:02    84.431n"
"26.07.2017  19:48:09    83.431n"
"26.07.2017  20:48:17    83.431n"
"26.07.2017  21:48:24    84.431n"
"26.07.2017  22:48:32    83.431n"
"26.07.2017  23:48:40    83.431n"
"27.07.2017  00:48:48    84.431n"
"27.07.2017  01:48:55    84.431n"
"27.07.2017  02:49:03    84.431n"
"27.07.2017  03:49:10    84.431n"
"27.07.2017  04:49:19    84.431n"
"27.07.2017  05:49:27    86.431n"
};
int
main()
{
using record = std::pair<date::sys_seconds, double>;
std::vector<record> records;
while (file)
{
record r;
file >> date::parse(" %d.%m.%Y %T", r.first) >> r.second;
if (file.fail())
break;
records.push_back(std::move(r));
}
std::sort(records.begin(), records.end(), [](const auto& x, const auto& y)
{return x.first < y.first;});
std::stable_sort(records.begin(), records.end(),
[](const auto& x, const auto& y)
{return x.second < y.second;});
records.erase(std::unique(records.begin(), records.end(),
[](const auto& x, const auto& y)
{return x.second == y.second;}),
records.end());
std::sort(records.begin(), records.end(), [](const auto& x, const auto& y)
{return x.first < y.first;});
for (const auto& r : records)
std::cout << date::format("%d.%m.%Y %T ", r.first) << r.second << 'n';
}

为了便于演示,我将您的data.tx放入了istringstream中。不要让那个细节绊倒你。CCD_ 12将与CCD_ 13或CCD_。

我正在重用std::pair作为我的record,但如果您愿意,您可以编写自己的record结构。在任何情况下,您都希望从数据库中收集vector<record>。这就是while循环的作用。这个循环使用Howard Hinnant的免费开源日期/时间库来解析时间戳,但也可以使用其他几种解决方案。

一旦从数据库中填写了records,就有三个std::algorithms将为您完成这项工作(分4步):

  1. 按时间戳对records进行排序。

  2. 压力稳定分选CCD_ 23。对于相等的压力,这将保留时间戳的排序顺序。

  3. 相等压力的唯一列表。该算法将重复的压力移动到列表的后面,并将迭代器返回到列表的"新端"。然后,您需要从[new_end, old_end)中擦除所有内容。

  4. 如果您希望按时间顺序查看列表,请最后一次按时间戳排序。

你完了!把它打印出来。这将输出:

26.07.2017 15:47:38 82.431
26.07.2017 16:47:46 83.431
26.07.2017 17:47:54 85.431
26.07.2017 18:48:02 84.431
27.07.2017 05:49:27 86.431

它与您想要的输出的前缀相匹配。

您的插入顺序似乎与日期/时间顺序相对应。如果是这样的话,你可以做一些类似的事情:

struct Record
{
std::chrono::system_clock::time_point time_point;
double pressure;
};
std::vector<Record> records = /**/;
const auto lessPressure = [](const auto& lhs, const auto& lhs){
return lhs.pressure < rhs.pressure;
};
std::stable_sort(records.begin(), records.end(), lessPressure);
const auto equalPressure = [](const auto& lhs, const auto& lhs){
return lhs.pressure == rhs.pressure;
};
records.erase(std::unique(records.begin(), records.end(), equalPressure), records.end());
const auto lessTimePoint = [](const auto& lhs, const auto& lhs){
return lhs.time_point< rhs.time_point;
};
std::sort(records.begin(), records.end(), lessTimePoint );

否则,从您的代码中,您必须将对pressure矢量所做的更改报告给其他数据:

所以改变:

for (k = j; k < (len - 1); k++)
pressure[k] = pressure[k + 1];

for (k = j; k < (len - 1); k++) {
pressure[k] = pressure[k + 1];
data[k] = data[k + 1];
time[k] = time[k + 1];
}

甚至

pressure.erase(pressure.begin() + j);
data.erase(data.begin() + j);
time.erase(time.begin() + j);