Làm cách nào để kiểm tra xem std :: map có chứa khóa mà không thực hiện thao tác chèn không?


147

Cách duy nhất tôi đã tìm thấy để kiểm tra các bản sao là bằng cách chèn và kiểm tra std::pair.secondcho false, nhưng vấn đề là điều này vẫn chèn một cái gì đó nếu quan trọng là không sử dụng, trong khi những gì tôi muốn là một map.contains(key);chức năng.


Câu trả lời:


304

Sử dụng my_map.count( key ); nó chỉ có thể trả về 0 hoặc 1, về cơ bản là kết quả Boolean mà bạn muốn.

Luân phiên my_map.find( key ) != my_map.end()làm việc quá.


40
@ John: Đó là sự tối ưu của việc tối ưu hóa sớm. Trên GCC (và tôi chắc chắn rằng các hệ thống hợp lý nhất), map::countđược triển khai như find(__x) == end() ? 0 : 1;. Đối với multimapbạn có thể có một đối số hiệu suất, nhưng đó không phải là câu hỏi của OP và tôi vẫn thích sự thanh lịch.
Potatoswatter

42
Không, đối số tối ưu hóa sớm chỉ có hiệu lực nếu việc tối ưu hóa mất một số nỗ lực mà trong trường hợp này thì không.
markh44

13
Không đúng. Sẽ không quá sớm nếu nó làm cho mã dễ đọc hơn hoặc loại bỏ các chi phí không cần thiết. Trong trường hợp này, nếu count () được thực hiện thông qua find () anyway, sau đó gọi find () trực tiếp loại bỏ một cuộc gọi chức năng ... ergo, nó trưởng thành tối ưu hóa. Tôi thấy rằng việc sử dụng lệnh find () cũng rõ ràng hơn, nhưng đó hoàn toàn là sở thích cá nhân.
Tim Keat

9
Nó không phải là một tối ưu hóa sớm để nhận thức được sự hoàn hảo của các chức năng thư viện trước khi bạn tạo thói quen sử dụng chúng. Trong trường hợp này, bạn đúng, điều đó không quan trọng, nhưng cũng không có sự khác biệt về phong cách rất nhỏ giữa tìm và đếm. Tôi nghĩ rằng bạn đã sử dụng biện pháp tu từ 'tối ưu hóa sớm' quá xa. Bạn nên thực hiện bất kỳ thói quen tối ưu hóa "miễn phí" nào bạn có thể tìm và sử dụng chúng cho sự phát triển hàng ngày. Đó là khi các lập trình viên chịu khuất phục trước cái bẫy phải trả chi phí về khả năng đọc / thời gian dev / v.v.
VoidStar

10
Xa ra, std chỉ nên thêm một lớp đồ chết tiệt has(k)/ contains(k)giống như mọi lớp bản đồ lành mạnh khác trên hành tinh. Thiết kế giao diện kém. Cách tiếp cận find () quá dài dòng và count(k)cách tiếp cận chắc chắn không ngang bằng ngữ nghĩa với has(k). Đối với vấn đề đó cũng không find(k). Kiểm tra số lượt xem cho câu hỏi này.
Jarrod Smith

46

Câu trả lời của Potatoswatter là ổn, nhưng tôi thích sử dụng findhoặc lower_boundthay vào đó. lower_boundđặc biệt hữu ích vì trình lặp được trả về sau đó có thể được sử dụng để chèn gợi ý, nếu bạn muốn chèn một cái gì đó với cùng một khóa.

map<K, V>::iterator iter(my_map.lower_bound(key));
if (iter == my_map.end() || key < iter->first) {    // not found
    // ...
    my_map.insert(iter, make_pair(key, value));     // hinted insertion
} else {
    // ... use iter->second here
}

Điều này khác biệt một cách tinh tế so với cách anh ấy nói rằng anh ấy đang làm điều đó. Điểm khác biệt duy nhất là tính toán valuecó thể bị bỏ qua nếu việc chèn là không cần thiết.
Potatoswatter

1
Chắc chắn, tôi hiểu rằng OP không quan tâm để chèn, vì vậy một lower_boundgiải pháp dựa trên cơ sở là quá mức cần thiết. Tôi chỉ đề cập đến câu trả lời của tôi "cho sự hoàn chỉnh"; Như tôi đã nói, của bạn là hoàn toàn đầy đủ. :-)
Chris Jester-Young

4
Đúng, đây là một câu trả lời hay và tôi không đồng ý với bất cứ điều gì. Chỉ cần chỉ ra mối quan hệ để thay thế insertmột tiên nghiệm. Trên thực tế, có một sự khác biệt khác nếu sử dụng a multimap, lower_boundphương thức chèn vào đầu phạm vi tương đương trong khi insertphương thức đơn giản thêm vào cuối phạm vi.
Potatoswatter

2
Không phải là câu trả lời cho câu hỏi, nhưng câu hỏi không hay của tôi đưa tôi đến câu trả lời đúng ở đây ... Tôi cần thực hiện thao tác chèn / cập nhật. : D
Hunter-Orionnoir 14/2/2015

1
@Hunter Bạn có thể cho tôi xem mã của bạn? Nếu nó không lớn, tôi có thể xem lại cho bạn.
Chris Jester-Young

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.