2011-10-05 31 views
10
map<T,Z> m= ...; 
vector<T> v; 
v.reserve(m.size); 
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it) 
{ 
v.push_back(it->first); 
} 

Có một phiên bản 1-line đẹp hơn sử dụng một số chức năng STL (s)?Sử dụng STL để cư một vector <T> từ bản đồ <T,Z> 's phím

chỉnh sửa: không sử dụng C++ 11!

+2

Overkill? Bạn không gõ quá nhiều dòng mã để đạt được điều này anyway. –

+0

@Als: bởi logic đó nhiều std :: thuật toán là như nhau vô ích. –

+0

@Mahesh - Tôi đang nghĩ về một số phép thuật phản xạ lại, hoặc một cái gì đó –

Trả lời

8

Portable:

struct SelectKey { 
    template <typename F, typename S> 
    F operator()(const std::pair<const F, S> &x) const { return x.first; } 
}; 

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey()); 

Tôi nghĩ rằng một số triển khai của STL có phần mở rộng phi tiêu chuẩn gọi là select1st, đó là tương đương với SelectKey đưa ra ở đây. Như K-Ballo đã chỉ ra trong các bình luận, đó cũng là một phiên bản TR1. Tôi thích phiên bản được đặt tên rõ ràng vì nó dễ dàng hơn để xem những gì đang xảy ra.

Kể từ khi không có nhu cầu về nhà nước, bạn có thể nhận được ngay với một chút ít soạn sẵn bằng cách sử dụng một chức năng thực tế chứ không phải là một functor:

template <typename F, typename S> 
F SelectKey()(const std::pair<const F, S> &x) { return x.first; } 

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey); 

Nếu bạn có thể sử dụng C++ 11, bạn có thể sử dụng một lambda, mà giữ mã lựa chọn gần nơi nó được sử dụng:

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), 
       [](const std::pair<const F, S> &x) { return x.first; }); 

hoặc thậm chí phạm vi dựa trên cho vòng lặp, mà có lẽ là thanh lịch nhất và dễ đọc:

for(const auto &x : m) { 
    v.push_back(x.first); 
} 
+1

Còn lambda thì sao? nó sẽ thực sự là một lớp lót. – Dani

+2

Toán tử 'của bạn()' phải là 'const'. Trong TR1, điều này có thể đạt được với 'std :: bind (& map < T, Z > :: value_type :: first, _1)'. –

+3

Không nên templatize cấu trúc, mà đúng hơn là toán tử '()'. Và nếu bạn thực sự muốn templatize cấu trúc, bạn nên cung cấp các đối số khi tạo nó: 'SelectKey ()'. – Xeo

2

Trong C++ 11, bạn có thể sử dụng biểu thức lambda:

typedef std::map< std::string, std::string > map_t; 
map_t map; 
std::vector<std::string> v; 

std::for_each(map.begin(), map.end(), [&v](map_t::value_type const& it) 
     { 
      v.push_back(it.first); 
     }); 
4

Pre C++ 11, bạn có thể sử dụng biến đổi và một chức năng tùy chỉnh struct:

template <class K, class V> 
struct key_selector : std::unary_function<const std::pair<K, V>&, const K&> 
{ 
    const K& operator()(const std::pair<K, V>& element) const 
    { 
     return element.first; 
    } 
}; 

transform(m.begin(), m.end(), back_inserter(v), key_selector<T,Z>()); 

Nếu bạn có truy cập vào tăng hoặc TR1, bạn có thể thay key_selector với mem_fn

transform(m.begin(), m.end(), back_inserter(v), mem_fn(&map<T,Z>::value_type::first)); 

sau thông C++ 11, bạn có thể sử dụng lambdas:

transform(m.begin(), m.end(), back_inserter(v), [](const map<T,Z>::value_type& x) {return x.first;}); 
+0

Ở trước C++ 11 bạn không thể sử dụng 'bind'. Nếu bạn dựa vào tiện ích mở rộng không phải là phần cứng hoặc tăng tốc, hãy nói như vậy. –

+0

@Christian: Đúng, với báo trước rằng trước C++ 11 bạn _could_ sử dụng 'std :: tr1 :: bind'. – ildjarn

+0

@ildjarn Có, nhưng sau đó anh ta nên nói như vậy và không giả vờ nó là tiêu chuẩn. –

1

Bạn có thể làm một cái gì đó dọc theo dòng:

std::transform(m.begin(), m.end(), std::back_inserter(v), FUNCTOR); 

đâu functor phụ thuộc vào những gì phiên bản của STL hoặc các thư viện và trình biên dịch mà bạn có.

C++ 11 (lambda)

std::transform(m.begin(), m.end(), std::back_inserter(v), [](map<T,Z>::const_reference a) { return a.first; }); 

C++ 11 (std :: get)

std::transform(m.begin(), m.end(), std::back_inserter(v), &std::get<0>); 

C++ SGI STL có một functor gọi select1st mà có thể được sử dụng

std::transform(m.begin(), m.end(), std::back_inserter(v), select1st); 

C++ 03 (Không C++ 11) sử dụng đối tượng functor như những người khác đã mô tả.

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