2017-10-11 79 views
2

我有一个3列的txt文件:"dd/mm/yyyy HH:MM:SS number(000.000)"。大约有368个条目。如何在命令中删除向量中的重复值?

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

在我的代码我在vectordtp)读取文件,然后填充每个columnvectordatatimepressure)。然后我删除第3列的值,并得到this

我的问题是如何添加第一和第二列与正确的指数,并得到this

数据实例(冷杉的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; 
} 
+4

欢迎来到Stack Overflow。请包括问题中的数据示例;不是链接,不是截图。 – Beta

+4

考虑将3个值保存在一个结构中。当你读取每个值时,将第3列添加到一个集合或一个unordered_set,如果它尚未存在,并且它抛弃了这些数据。 –

+0

@贝塔感谢您的意见 – dfdd

回答

1

我认为你会做的更好认为这是一个表,两列:

Timestamp Pressure 

有了这样的工作,而不是。要使用时间戳,它有助于使用date/time library which can parse, format and order time stamps

以下是它的样子。详细说明下面的代码:

#include "date/date.h" 
#include <algorithm> 
#include <iostream> 
#include <sstream> 
#include <utility> 
#include <vector> 

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

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.txistringstream。不要让这些细节让你感动。 main将与istringstreamifstream一样正常工作。如果您愿意,可以自己编写record结构。无论如何,你想从你的数据库中收集一个vector<record>。这就是while循环所做的。此循环使用Howard Hinnant's free, open-source date/time library解析时间戳,但还有其他几种解决方案可供您使用。

一旦你有records从数据库填充,有三个std::algorithms会做这个工作对你(4级):

  1. 排序records通过时间戳。

  2. 稳定排序records受压。对于相同的压力,这保留了时间戳的排序顺序。

  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 

它匹配所需输出的前缀。

+0

谢谢您,这真的很美。我是对的,汽车和只在C + + 14标准版? – dfdd

+0

这是正确的。对于C++ 11,您需要在lambda参数中为'auto'记录'record'。 –

0

看来您的插入顺序对应的日期/时间顺序。如果是这样的话,你可以这样做:

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); 
+0

感谢您的帮助,会理解您的代码,以达到新知识 – dfdd