2017-10-11 80 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