std ::지도를 통한 루프에서 마지막 반복을 어떻게 감지 할 수 있습니까?
문제
다음과 같은 작업을 수행하기 위해지도를 통해 루프를 마지막으로 반복하는지 여부를 결정하는 가장 좋은 방법을 찾으려고 노력하고 있습니다.
for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
bool last_iteration;
// do something for all iterations
if (!last_iteration) {
// do something for all but the last iteration
}
}
이 작업을 수행하는 몇 가지 방법이있는 것 같습니다 : 임의의 액세스 반복자, distance
기능 등. 표준 방법은 무엇입니까?
편집 :지도 용 임의의 액세스 반복자가 없습니다!
해결책
정지? 나는 그것을 주장 할 수 없지만 제안 할 것입니다
final_iter = someMap.end();
--final_iter;
if (iter != final_iter) ...
편집 제안한대로 수정합니다 KTC. (감사합니다! 때때로 당신은 너무 빨리 가서 가장 간단한 것들을 엉망으로 만들었습니다 ...)
다른 팁
C ++ 11이므로 std :: next ()를 사용할 수도 있습니다.
for (auto iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (std::next(iter) != someMap.end()) {
// do something for all but the last iteration
}
}
질문이 얼마 전에 질문을 받았지만, 나는 그것이 공유 할 가치가 있다고 생각했습니다.
이것은 가장 간단한 것 같습니다.
bool last_iteration = iter == (--someMap.end());
Forweriterator를 사용하려면 다음과 같습니다.
for ( i = c.begin(); i != c.end(); ) {
iterator cur = i++;
// do something, using cur
if ( i != c.end() ) {
// do something using cur for all but the last iteration
}
}
수정 된 Mark Ransom은 실제로 의도 한대로 작동합니다.
finalIter = someMap.end();
--finalIter;
if (iter != final_iter)
아직 아무도 언급하지 않았지만 물론 부스트는 무언가를 가지고 있습니다.)
boost.next (및 동등한 부스트.
예제는 다음과 같습니다.
for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (boost::next(iter) != someMap.end()) {
// do something for all but the last iteration
}
}
다음 코드는 컴파일러에 의해 최적화되므로 OOP 규칙뿐만 아니라 성능에 의해이 작업에 가장 적합한 솔루션이되도록합니다.
if (&*it == &*someMap.rbegin()) {
//the last iteration
}
std :: map은 다음과 같은 코드에 대한 특수 회원 함수 rbegin을 받았기 때문에 OOP 규칙에 따른 최고의 코드입니다.
final_iter = someMap.end();
--final_iter;
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>
using namespace boost::lambda;
// call the function foo on each element but the last...
if( !someMap.empty() )
{
std::for_each( someMap.begin(), --someMap.end(), bind( &Foo, _1 ) );
}
std :: for_each를 사용하면 루프가 빡빡하고 정확한지 확인합니다 ... 단일 인수를 취하는 함수 foo ()의 도입 (유형은 Somemap에 포함 된 내용과 일치해야 함). 이 접근법은 1 라인이 추가되었습니다. 물론 FOO가 실제로 작 으면 Lambda 기능을 사용하고 & foo에 대한 호출을 제거 할 수 있습니다.
당신이 그것에 무언가를주지 않도록 EOF를 찾기 위해 일하는 이유.
간단히 말해서 배제하십시오.
for (iter = someMap.begin(); someMap.end() - 1; ++iter) {
//apply to all from begin to second last element
}
키스 (간단하게 유지)
간단하고 효과적인 접근 방식 :
size_t items_remaining = someMap.size();
for (iter = someMap.begin(); iter != someMap.end(); iter++) {
bool last_iteration = items_remaining-- == 1;
}
내 최적화 된 테이크는 다음과 같습니다.
iter = someMap.begin();
do {
// Note that curr = iter++ may involve up to three copy operations
curr = iter;
// Do stuff with curr
if (++iter == someMap.end()) {
// Oh, this was the last iteration
break;
}
// Do more stuff with curr
} while (true);
어때요, 아무도 언급하지 않았지만 ...
for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (iter != --someMap.end()) {
// do something for all but the last iteration
}
}
이것은 간단 해 보인다, MM ...
전체 프로그램 :
#include <iostream>
#include <list>
void process(int ii)
{
std::cout << " " << ii;
}
int main(void)
{
std::list<int> ll;
ll.push_back(1);
ll.push_back(2);
ll.push_back(3);
ll.push_back(4);
ll.push_back(5);
ll.push_back(6);
std::list<int>::iterator iter = ll.begin();
if (iter != ll.end())
{
std::list<int>::iterator lastIter = iter;
++ iter;
while (iter != ll.end())
{
process(*lastIter);
lastIter = iter;
++ iter;
}
// todo: think if you need to process *lastIter
std::cout << " | last:";
process(*lastIter);
}
std::cout << std::endl;
return 0;
}
이 프로그램은 다음과 같습니다.
1 2 3 4 5 | last: 6
반복 전에 맵에서 요소를 꺼낸 다음 "마지막 반복"을 루프에서 수행 한 다음 요소를 다시 넣을 수 있습니다. ~ 안으로 지도. 이것은 비동기 코드의 경우 끔찍하게 나쁘지만 C ++의 나머지 부분이 동시성에 얼마나 나쁜지를 고려할 때 문제가 될 것이라고 생각하지 않습니다. :-)