2012-06-15 25 views
5

Tôi muốn lấy các phần tử được sắp xếp theo số lần xuất hiện của chúng. Đây là những gì tôi đã đưa ra (mHeights là một std :: MultiSet):Cách sắp xếp một bội số cho vùng chứa theo số lần xuất hiện phần tử

namespace{ 
    template<class U,class T> 
    class HistPair{ 
    public: 
     HistPair(U count,T const& el):mEl(el),mNumber(count){  
     } 
     T const& getElement()const{return mEl;} 

     U getCount()const{return mNumber;} 
    private: 
     T mEl; 
     U mNumber; 
    }; 

    template<class U,class T> 
    bool operator <(HistPair<U,T> const& left,HistPair<U,T> const& right){ 
    return left.getCount()< right.getCount(); 
    } 
} 

std::vector<HistPair<int,double> > calcFrequentHeights(){ 
    typedef HistPair<int,double> HeightEl; 
    typedef std::vector<HistPair<int,double> > Histogram; 
    std::set<double> unique(mHeights.begin(),mHeights.end()); 
    Histogram res; 
    boostForeach(double el, unique) { 
    res.push_back(HeightEl(el,mHeights.count(el)));  
    } 
    std::sort(res.begin(),res.end()); 
    std::reverse(res.begin(),res.end()); 
    return res; 
} 

Vì vậy, đầu tiên tôi thực hiện tất cả các yếu tố độc đáo từ MultiSet, sau đó tôi đếm chúng và sắp xếp chúng vào một container mới (I cần số lượng để tôi sử dụng bản đồ). Điều này có vẻ khá phức tạp cho một nhiệm vụ dễ dàng như vậy. Ngoài HistPair, được sử dụng ở nơi khác, không có bất kỳ thuật toán stl nào để đơn giản hóa tác vụ này, ví dụ: sử dụng equal_range hoặc sth. như nhau.

Edit: Tôi cần số lần xuất hiện là tốt, xin lỗi tôi quên mất rằng

+1

Trông khá ngắn gọn với tôi . Tôi không thể tưởng tượng bạn có kế hoạch nhiều hơn một hoặc hai dòng trong thói quen tạo biểu đồ của bạn. Một thay thế có thể là sử dụng một 'std :: map ' thay vì 'std :: multiset ' và tính toán kích thước thùng của bạn khi bạn chèn các phần tử, nhưng nó sẽ không thay đổi nhiều. – Rook

+0

@nims: Đó là những gì tôi đang làm hoặc tôi hiểu lầm bạn. Tôi cần đếm và yếu tố – Martin

+0

@ Bắt đầu xấu của tôi, bỏ qua nó. – nims

Trả lời

6

đoạn này làm những gì bạn muốn, bằng cách kết hợp một std::set, một lambda và std::multiset::count:

#include <iostream> 
#include <set> 
#include <vector> 
#include <algorithm> 

int main() { 
    std::multiset<int> st; 
    st.insert(12); 
    st.insert(12); 
    st.insert(12); 
    st.insert(145); 
    st.insert(145); 
    st.insert(1); 
    st.insert(2); 

    std::set<int> my_set(st.begin(), st.end()); 
    std::vector<int> my_vec(my_set.begin(), my_set.end()); 
    std::sort(my_vec.begin(), my_vec.end(), 
     [&](const int &i1, const int &i2) { 
      return st.count(i1) < st.count(i2); 
     } 
    ); 

    for(auto i : my_vec) { 
     std::cout << i << " "; 
    } 
    std::cout << std::endl; 
} 

Bạn có thể đặt muốn đảo ngược vectơ. Đây quả đầu ra:

1 2 145 12 

Sửa: Đi vào tài khoản bạn cũng cần tính mục, điều này sẽ làm điều đó:

#include <iostream> 
#include <set> 
#include <vector> 
#include <algorithm> 

int main() { 
    typedef std::vector<std::pair<int, int>> MyVector; 
    std::multiset<int> st; 
    st.insert(12); 
    st.insert(12); 
    st.insert(12); 
    st.insert(145); 
    st.insert(145); 
    st.insert(1); 
    st.insert(2); 

    std::set<int> my_set(st.begin(), st.end()); 
    MyVector my_vec; 
    my_vec.reserve(my_set.size()); 

    for(auto i : my_set) 
     my_vec.emplace_back(i, st.count(i)); 

    std::sort(my_vec.begin(), my_vec.end(), 
     [&](const MyVector::value_type &i1, const MyVector::value_type &i2) { 
      return i1.second < i2.second; 
     } 
    ); 

    for(const auto &i : my_vec) 
     std::cout << i.first << " -> " << i.second << std::endl; 
} 

Những kết quả đầu ra:

1 -> 1 
2 -> 1 
145 -> 2 
12 -> 3 
+0

Cảm ơn. Lambdas chỉ là tiện dụng ;-) Tuy nhiên tôi quên đề cập đến rằng tôi cần đếm là tốt, nhưng điều này không phải là khó khăn để tích hợp vào giải pháp của bạn – Martin

+0

Có bạn đi, editted câu trả lời của tôi. – mfontanini

+0

Cảm ơn bạn lần nữa !!! – Martin