2011-12-09 40 views
5

cho phép nói rằng tôi có một số vector của pair<int,int>. Bây giờ tôi muốn trích xuất các vector pair.firstpair.second làm các vectơ độc lập. Tôi có thể lặp lại trên vector và làm điều đó nhưng có cách nào tốt hơn/nhanh hơn không?Cách nhanh nhất để chuyển đổi từ vectơ của các cặp thành hai vectơ độc lập trong C++

+0

Tôi không thấy cách nào làm cho nó nhanh hơn vòng lặp trên tất cả các mục trong vectơ. Tuy nhiên, bạn không phải tự mình lặp lại, sử dụng một cái gì đó như ['std :: for_each'] (http://en.cppreference.com/w/cpp/algorithm/for_each). –

+0

Bạn có chắc chắn rằng bạn cần phải sao chép các giá trị vào các vectơ mới? Có lẽ bạn có thể sử dụng [transform_iterators] (http://www.boost.org/doc/libs/release/libs/iterator/doc/transform_iterator.html) để chỉ đơn giản là lặp lại trên vector ban đầu trong khi nhận được các phần tử cặp, mà không cần sao chép chúng ở nơi khác. –

+0

có. nhưng tôi không muốn sử dụng tăng cường. Dù sao, mọi người đều đưa ra câu trả lời đúng để tôi chấp nhận câu trả lời với 'chi tiết' tốt nhất. – Neal

Trả lời

11

Trong C++ 11, nếu bạn không cần vector cũ nữa, bạn có lẽ có thể có được một chút hiệu quả thêm từ ngữ nghĩa di chuyển:

for (auto it = std::make_move_iterator(v.begin()), 
     end = std::make_move_iterator(v.end()); it != end; ++it) 
{ 
    v1.push_back(std::move(it->first)); 
    v2.push_back(std::move(it->second)); 
} 

Ngoài ra, bạn chắc chắn không thể làm tốt hơn một vòng lặp. Bạn sẽ phải chạm vào mọi phần tử ít nhất một lần, vì vậy điều này hiệu quả như nó nhận được.

Lưu ý rằng việc di chuyển chỉ có thể tạo sự khác biệt nếu các phần tử tự có các ngữ nghĩa di chuyển tốt hơn so với sao chép. Đây không phải là trường hợp của int s hoặc bất kỳ POD nào. Nhưng nó không thể làm tổn thương để viết mã của bạn một cách tổng quát để bạn có thể tận dụng điều này trong các tình huống trong tương lai.

Nếu sao chép/di chuyển là một vấn đề, tuy nhiên, bạn nên cân nhắc xem một số bộ điều hợp chế độ xem cho vectơ gốc có thể là cách tiếp cận tốt hơn hay không.

+1

Whoa, không bao giờ biết về 'make_move_iterator', +1 –

+0

@SethCarnegie: Thực ra tôi nghi ngờ nó cần thiết ở đây; Tôi chỉ cần đặt nó vào cho vui ('std :: move' nên đã làm các trick). Trình biến đổi di chuyển rất hữu ích cho các thuật toán. Nó được gói sẵn trong ['algorithm/std :: move'] (http://en.cppreference.com/w/cpp/algorithm/move), là phiên bản di chuyển của' std :: copy'. –

+0

@KerrekSB: Và hiệu quả bổ sung * sẽ đến từ đâu? Tôi không nghĩ rằng điều này sẽ hiệu quả hơn vòng lặp đơn giản hơn - đó cũng là lý do dễ dàng hơn. –

3

Không có. Một điều cần lưu ý là sử dụng reserve trên hai véc-tơ kết quả để ngăn chặn sự phân bổ lại không cần thiết.

1

Bạn phải lặp lại trên vectơ, vì vậy về mặt độ phức tạp, điều này là tốt như bạn có thể nhận được.

2

Bạn sẽ không thể tránh lặp lại. Theo giải pháp nhanh nhất, nó phụ thuộc vào những gì có trong cặp, và về việc thực hiện thực tế. Tùy thuộc vào những điều này, có thể tốt hơn để tạo các vectơ mục tiêu với kích thước chính xác và gán cho chúng là ; hoặc để tạo chúng trống và sử dụng reserve và sau đó push_back. Bạn cũng có thể muốn so sánh lập chỉ mục bằng cách sử dụng trình vòng lặp; nếu bạn đang sử dụng các vectơ có kích thước trước, chỉ sử dụng một biến số kiểm soát thay vì ba có thể là một cải tiến. (Với g ++, lần cuối cùng tôi đo, tạo vector có kích thước chính xác và ấn định là nhanh hơn so với sử dụng reservepush_back, ít nhất là cho double. Mặc dù thực tế rằng nó có nghĩa là vòng lặp hai lần trong nội bộ, và khởi tạo các giá trị để 0.0.)

bạn cũng có thể muốn thử tạo các đối tượng chức năng để trích xuất các yếu tố đầu tiên và thứ hai của cặp (giả bạn không có họ đã được), và sử dụng hai cuộc gọi đến transform. Một lần nữa, hoặc là với một véc tơ được xác định trước là hoặc sử dụng dấu chèn ngược trở lại làm mục tiêu. Mặt khác, tôi sẽ không mong đợi điều này để cung cấp hiệu suất tốt hơn, nhưng bạn không bao giờ biết.

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