Trong std :: multiset có một hàm hoặc thuật toán để xóa chỉ một mẫu (đơn lẻ hoặc trùng lặp) nếu một phần tử được tìm thấy


83

Có lẽ đây là một bản sao nhưng tôi không tìm thấy bất cứ điều gì khi tìm kiếm: Khi erase(value)được gọi trên std::multisettất cả các phần tử có giá trị được tìm thấy đều bị xóa. Giải pháp duy nhất tôi có thể nghĩ ra là:

std::multiset<int>::iterator hit(mySet.find(5));
if (hit!= mySet.end()) mySet.erase(hit);

Điều này là ổn nhưng tôi nghĩ có thể tốt hơn. Bất kỳ ý tưởng?


22
Đây là một cách tiếp cận hoàn toàn hợp lý.
templatetypedef

Cách tiếp cận này có đảm bảo rằng khóa đã cho ("5") là trùng lặp không?
Arun

@ArunSaha: Không. Nhưng nếu nó không phải là bản sao, tôi muốn xóa nó đi. Từ những câu trả lời tôi nhận được, tôi có cảm giác rằng không có giải pháp nào tốt hơn. Có lẽ câu hỏi là ngu ngốc ở nơi :-P đầu tiên
Martin

1
Đối với multimap: có bất kỳ đảm bảo về các yếu tố findtrả lại? (Trình tự chèn Ngay cả sau khi tẩy xoá này thực hiện phụ thuộc??)
P Marecki

2
Thành thật mà nói, đó là một cạm bẫy không thể thấy được khi sử dụng nhiều bộ không nằm trong số các lớp được sử dụng thường xuyên nhất.
Predelnik

Câu trả lời:


32
auto itr = my_multiset.find(value);
if(itr!=my_multiset.end()){
    my_multiset.erase(itr);
}

Tôi sẽ tưởng tượng có một cách hoàn thành tương tự dễ dàng hơn. Nhưng điều này sẽ hoàn thành công việc.


7
Điều này không khác gì những gì trong câu hỏi.
Troubadour

1
Tôi đồng ý! Không có ý nghĩa gì. 12 người khác đã thấy điều gì đó hữu ích trong câu trả lời nên tôi biết mình sẽ không phát điên.
user2251346

6
Không bao giờ bỏ qua những khả năng mà bạn sẽ điên cùng với những người khác :)
Apollys hỗ trợ Monica

15

Hãy thử cái này:

multiset<int> s;
s.erase(s.lower_bound(value));

Miễn là bạn có thể đảm bảo rằng các valuelối ra trong tập hợp. Điều đó hoạt động.


2
 if(my_multiset.find(key)!=my_multiset.end())
   my_multiset.erase(my_multiset.equal_range(key).first);

Đây là cách tốt nhất tôi có thể nghĩ ra để loại bỏ một trường hợp duy nhất trong một tập hợp đa năng trong c ++


1
So với giải pháp tôi đã đề xuất trong câu hỏi, mã của bạn thực hiện hai tìm kiếm (find + equal_range) thay vì một tìm kiếm không hiệu quả
Martin

vì đây là cùng một độ phức tạp, tôi rất thích câu trả lời này. Cảm ơn bạn
Crystal

1

Tôi sẽ thử những điều sau đây.

Đầu tiên cuộc gọi equal_range()để tìm phạm vi của các phần tử bằng khóa.

Nếu phạm vi được trả về là không trống, thì erase()một phạm vi các phần tử (tức là phạm vi erase()có hai trình vòng lặp) trong đó:

  • đối số đầu tiên là trình lặp đến phần tử thứ 2 trong phạm vi được trả về (tức là một trong quá khứ được .firsttrả về) và

  • đối số thứ hai là đối số được trả về của trình lặp cặp phạm vi .second.


Chỉnh sửa sau khi đọc bình luận (Cảm ơn!) Của templatetypedef :

Nếu một (trái ngược với tất cả) bản sao phải bị xóa: Nếu cặp được trả về equal_range()có ít nhất hai phần tử, thì erase()phần tử đầu tiên bằng cách chuyển phần tử đầu tiên của cặp được trả về thành phiên bản trình lặp đơn của erase():

Mã giả:

pair<iterator, iterator> pit = mymultiset.equal_range( key );

if( distance( pit.first, pit.second ) >= 2 ) {
    mymultiset.erase( pit.first );
}

2
Tôi nghĩ câu hỏi đang đặt ra về việc loại bỏ chỉ một bản sao, không phải tất cả các bản sao.
templatetypedef

Bạn có ý tưởng liệu điều này có nhanh hơn giải pháp của tôi không và nếu có thì tại sao?
Martin

1

Điều này đã làm việc cho tôi:

multi_set.erase(multi_set.find(val));

nếu val tồn tại trong nhiều tập hợp.


0

Chúng ta có thể làm điều gì đó như sau:

multiset<int>::iterator it, it1;
it = myset.find(value);
it1 = it;
it1++;
myset.erase (it, it1);

1
Quá mức cần thiết. "Bộ lặp chỉ đến một phần tử duy nhất cần được xóa khỏi tập hợp không có thứ tự."
Andrew

-3

Trên thực tế, câu trả lời chính xác là:

my_multiset.erase(my_multiset.find(value));

1
Nếu giá trị không tồn tại trong tập hợp nhiều, nó gây ra hành vi không xác định .
kien_coi_1997 23/02/15
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.