2012-02-11 36 views
9

Tôi có một vector của chuỗi:bản sao Loại bỏ trong một vector của chuỗi

std::vector<std::string> fName 

nắm giữ một danh sách tên tập tin <a,b,c,d,a,e,e,d,b>.

Tôi muốn loại bỏ tất cả các tệp có bản sao và chỉ muốn giữ lại các tệp không có bản sao trong vectơ.

for(size_t l = 0; l < fName.size(); l++) 
{ 
    strFile = fName.at(l); 
    for(size_t k = 1; k < fName.size(); k++) 
    { 
     strFile2 = fName.at(k); 
     if(strFile.compare(strFile2) == 0) 
     { 
      fName.erase(fName.begin() + l); 
      fName.erase(fName.begin() + k); 
     } 
    } 
} 

Thao tác này sẽ xóa một số trùng lặp nhưng vẫn còn một số bản sao còn lại, cần trợ giúp gỡ lỗi.

Ngoài ra đầu vào của tôi trông giống như <a,b,c,d,e,e,d,c,a> và kết quả mong đợi của tôi là <b> vì tất cả các tệp khác b, c, d, e có các bản sao bị xóa.

+0

Bạn có muốn giữ bản sao của các bản sao không? I E. bạn có muốn hoặc chỉ không? –

+0

Tôi không muốn giữ bản sao của bản dupilcates. –

Trả lời

11
#include <algorithm> 

template <typename T> 
void remove_duplicates(std::vector<T>& vec) 
{ 
    std::sort(vec.begin(), vec.end()); 
    vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); 
} 

Lưu ý: điều này yêu cầu T có operator<operator== được xác định.

Tại sao nó hoạt động?

std::sort loại các yếu tố sử dụng của họ ít hơn toán tử so sánh

std::unique loại bỏ các yếu tố trùng lặp liên tiếp, so sánh chúng bằng toán tử so sánh bằng họ

gì nếu tôi muốn chỉ là yếu tố duy nhất?

Sau đó, bạn sử dụng tốt hơn std :: map

#include <algorithm> 
#include <map> 

template <typename T> 
void unique_elements(std::vector<T>& vec) 
{ 
    std::map<T, int> m; 
    for(auto p : vec) ++m[p]; 
    vec.erase(transform_if(m.begin(), m.end(), vec.begin(), 
         [](std::pair<T,int> const& p) {return p.first;}, 
         [](std::pair<T,int> const& p) {return p.second==1;}), 
      vec.end()); 
} 

Xem: here.

+0

Cũng cần bao gồm #include cho std :: sort and std :: unique to work. –

+0

Gigi cảm ơn bạn đã làm việc này nhưng không giải quyết được vấn đề ban đầu của tôi ... Tôi bắt đầu với Tôi muốn đầu ra của mình là và không

+0

Xin lỗi tôi muốn đầu ra của tôi là không được lặp lại. –

3

Nếu tôi hiểu yêu cầu của bạn một cách chính xác và tôi không hoàn toàn chắc chắn rằng tôi làm. Bạn chỉ muốn giữ các phần tử trong vectơ mà không lặp lại, đúng không?

Tạo bản đồ các chuỗi thành int, được sử dụng để đếm số lần xuất hiện của mỗi chuỗi. Xóa vector, sau đó sao chép lại chỉ các chuỗi chỉ xuất hiện một lần.

map<string,int> m; 
for (auto & i : v) 
    m[i]++; 
v.clear(); 
for (auto & i : m) 
    if(i.second == 1) 
     v.push_back(i.first); 

Hoặc, đối với trình biên dịch-tính năng thách thức:

map<string,int> m; 
for (vector<string>::iterator i=v.begin(); i!=v.end(); ++i) 
    m[*i]++; 
v.clear(); 
for (map<string,int>::iterator i=m.begin(); i!=m.end(); ++i) 
    if (i->second == 1) 
     v.push_back(i->first); 
2
#include <algorithms> 

template <typename T> 
remove_duplicates(std::vector<T>& vec) 
{ 
    std::vector<T> tvec; 
    uint32_t size = vec.size(); 
    for (uint32_t i; i < size; i++) { 
    if (std::find(vec.begin() + i + 1, vec.end(), vec[i]) == vector.end()) { 
     tvec.push_back(t); 
    } else { 
     vec.push_back(t); 
    } 
    vec = tvec; // :) 
    } 
} 
+0

rõ ràng điều này là không hiệu quả – perreal

+1

' std :: vector' không có 'pop_front()' –

+0

chỉ có pop_back() không thể tìm thấy một pop_front(). Ông Lindley sẽ là tuyệt vời nếu bạn có thể giúp đỡ, cảm ơn bạn perreal –

0

Bạn có thể loại bỏ các bản sao trong thời gian O (log n) thời gian chạy và O (n) không gian:

std::set<std::string> const uniques(vec.begin(), vec.end()); 
vec.assign(uniques.begin(), uniques.end()); 

Nhưng thời gian chạy O (log n) là một chút gây hiểu lầm, bởi vì không gian O (n) thực sự phân bổ động O (n), mà là tốn kém về tốc độ. Các yếu tố cũng phải được so sánh (ở đây với operator<(), trong đó std::string hỗ trợ như so sánh từ điển).

Nếu bạn muốn lưu trữ các yếu tố chỉ duy nhất:

template<typename In> 
In find_unique(In first, In last) 
{ 
    if(first == last) return last; 
    In tail(first++); 
    int dupes = 0; 
    while(first != last) { 
     if(*tail++ == *first++) ++dupes; 
     else if(dupes != 0) dupes = 0; 
     else return --tail; 
    } 
    return dupes == 0 ? tail : last; 
} 

Các thuật toán trên có một loạt sắp xếp và trả về phần tử độc đáo đầu tiên, trong thời gian tuyến tính và không gian liên tục. Để có được tất cả các đồ cổ trong một thùng chứa, bạn có thể sử dụng nó như vậy:

auto pivot = vec.begin(); 
for(auto i(find_unique(vec.begin(), vec.end())); 
    i != vec.end(); 
    i = find_unique(++i, vec.end())) { 
    std::iter_swap(pivot++, i); 
} 
vec.erase(pivot, vec.end()); 
+0

Để được thẳng thắn tôi muốn đi với 'std :: sort()' và 'std :: unique()' phương pháp tiếp cận Tôi chỉ nghĩ rằng tôi muốn hiển thị một thay thế. :) – wilhelmtell

+0

một ví dụ khủng khiếp trong mọi trường hợp (hiệu suất, vv), mùi giống như một workaround cho những người lười biếng, đủ để không kiểm tra các thuật toán thư viện – newhouse

0

Mặc dù nó đã được trả lời.

sắp xếp và duy nhất

Các vấn đề liên quan