2009-11-27 73 views
6

Vì không có hàm .resize() trong C++ std :: map Tôi đã tự hỏi, làm thế nào người ta có thể có được một std :: map với nhiều nhất n phần tử .Làm thế nào để có được các phần tử n đầu tiên của một std :: map

Giải pháp hiển nhiên là tạo vòng lặp từ 0 đến n và sử dụng trình lặp thứ n làm thông số đầu tiên cho std :: erase().

Tôi đã tự hỏi nếu có bất kỳ giải pháp nào không cần vòng lặp (ít nhất không phải trong mã người dùng của tôi) và có nhiều "cách STL để đi".

+1

Hmm .. Tôi muốn nói sử dụng vòng lặp lặp * là * cách STL, phải không? – schnaader

+2

Không có 'std :: erase'. Sử dụng 'std :: map :: erase()' –

Trả lời

13

Bạn có thể sử dụng std::advance(iter, numberofsteps) cho điều đó.

+0

+1 - không biết điều đó - đẹp nhất. – schnaader

0

Tại sao bạn muốn thay đổi kích thước bản đồ?

Các yếu tố trong một bản đồ không được lưu trữ trong bất kỳ thứ tự - những 'n' đầu tiên không thực sự có ý nghĩa gì

chỉnh sửa:
Điều thú vị là std :: bản đồ không có một trật tự, không chắc chắn cách hữu ích khái niệm này là.
Các mục nhập có cùng thứ tự sắp xếp với các phím không?
Điều đó có nghĩa là gì? Nếu bạn có Tên được khóa bởi SSN, điều đó có nghĩa là các tên được lưu trữ trong thứ tự số SSN không?

+0

Không phải là các phần tử được sắp xếp theo khóa? –

+0

Không theo cách bạn nghĩ, các yếu tố trong một số thứ tự trong bộ nhớ. Có một thuật toán băm chuyển đổi khóa thành một chỉ mục. Nhưng các yếu tố cho key1 và key2 không nhất thiết phải cạnh nhau. –

+3

@mgb Không, đó sẽ là bảng băm. Một std :: map là một cây tìm kiếm nhị phân (thường là một cây màu đỏ-đen được cụ thể). Các yếu tố trong một std :: bản đồ do đó được lưu trữ trong một cách mà làm cho iterating theo thứ tự dễ dàng và nhanh chóng. – Tim

1

A std :: map không phải là danh sách. Không có yếu tố "đầu tiên".

BTW: Bộ lặp sẽ trở thành không hợp lệ nếu vùng chứa được thay đổi.

Nếu bạn thực sự cần một bản đồ nhỏ hơn, bạn có thể lặp lại mặc dù nó và thêm tất cả các phần tử vào thứ n vào bản đồ mới.

+3

Vâng, các yếu tố được sắp xếp theo khóa của họ phải không? – Nailer

+0

@Nailer: Nice, tôi không biết điều đó. Liên kết này xác nhận: http://www.cplusplus.com/reference/stl/map/ – ya23

+1

Có, họ đang có. Nhưng một bản đồ là "rất có thể được thực hiện như một cây cân bằng của các nút" (trích dẫn "Ngôn ngữ lập trình C++", Bjarne Stroustrup), không phải là một danh sách. Vì vậy, mymap [n] không có ý nghĩa gì cả. – EricSchaefer

3

Giải pháp phổ dụng cho hầu hết mọi vùng chứa, chẳng hạn như std :: list, std :: map, boost :: multi_index. Bạn chỉ phải kiểm tra kích thước bản đồ của mình.

template<class It> 
It myadvance(It it, size_t n) { 
    std::advance(it, n); 
    return it; 
} 

template<class Cont> 
void resize_container(Cont & cont, size_t n) { 
    cont.erase(myadvance(cont.begin(), std::min(n, cont.size())), 
       cont.end()); 
} 
+0

nó void std :: advance(), do đó, điều này đã không biên dịch. – Norbert

+0

Phải. Tôi sửa rồi. –

+0

+1, nhưng nếu bạn đã dọn dẹp để giải phóng, bạn sẽ phải quyết định khái niệm 'resize_container' hoạt động như thế nào. Tên tham số của hàm và mẫu cho thấy bất kỳ vùng chứa nào. Tên tham số chức năng gợi ý bất kỳ bản đồ nào. Như được viết, tôi nghĩ rằng nó sẽ thực sự hoạt động trên bất kỳ Sequence hoặc Associative Container nào, điều này không may có nghĩa là miền của nó là một nhóm polyphy thể trong phân loại C++. –

1

Cách chính xác cho việc này là sử dụng lệnh std :: advance. Nhưng đây là một cách hài hước (chậm) cho phép 'sử dụng thay đổi kích thước trên bản đồ'. Nói chung, loại lừa này có thể được sử dụng cho những thứ khác làm việc trên vector nhưng không phải trên bản đồ.

map<K,V> m; //your map 
vector< pair<K,V> > v(m.begin(), m.end()); 
v.resize(n); 
m = map<K,V>(v.begin(),v.end()); 
Các vấn đề liên quan