IT TIP

벡터를 반복하고 특정 항목을 제거합니다.

itqueen 2020. 11. 25. 21:47
반응형

벡터를 반복하고 특정 항목을 제거합니다.


std :: vector m_vPaths가 있습니다. 이 벡터를 반복하고 이동하면서 :: DeleteFile (strPath)를 호출합니다. 파일을 성공적으로 삭제하면 벡터에서 제거합니다. 내 질문은 두 개의 벡터를 사용해야하는 문제를 해결할 수 있습니까? 수행해야하는 작업에 더 적합한 다른 데이터 구조가 있습니까?

예 : 반복기를 사용하면 내가 원하는대로 거의 수행되지만 문제는 반복기를 사용하여 지우면 모든 반복기가 무효화된다는 것입니다.

 std::vector<std::string> iter = m_vPaths.begin();
    for( ; iter != m_vPaths.end(); iter++) {
        std::string strPath = *iter;
        if(::DeleteFile(strPath.c_str())) {
            m_vPaths.erase(iter);   
                //Now my interators are invalid because I used erase,
                //but I want to continue deleteing the files remaining in my vector.    
        }
    }

두 개의 벡터를 사용할 수 있고 더 이상 문제가 발생하지 않지만 수행하려는 작업을 수행하는 더 좋고 효율적인 방법이 있습니까?

btw, 명확하지 않은 경우 m_vPaths는 다음과 같이 선언됩니다 (내 수업에서).

std::vector<std::string> m_vPaths;

확인 std::remove_if:

#include <algorithm> // for remove_if
#include <functional> // for unary_function

struct delete_file : public std::unary_function<const std::string&, bool> 
{
    bool operator()(const std::string& strPath) const
    {
        return ::DeleteFile(strPath.c_str());
    }
}

m_vPaths.erase(std::remove_if(m_vPaths.begin(), m_vPaths.end(), delete_file()),
                m_vPaths.end());

std::list임의 액세스를 잃어도 유효하지 않은 반복기 문제를 중지 하려면 a 사용하십시오 . (일반적으로 캐시 성능)


기록을 위해 코드를 구현하는 방법은 다음과 같습니다.

typedef std::vector<std::string> string_vector;
typedef std::vector<std::string>::iterator string_vector_iterator;

string_vector_iterator iter = m_vPaths.begin();
while (iter != m_vPaths.end())
{
    if(::DeleteFile(iter->c_str()))
    {
        // erase returns the new iterator
        iter = m_vPaths.erase(iter);
    }
    else
    {
        ++iter;
    }
}

그러나 당신은 사용해야합니다 std::remove_if(바퀴를 재발 명하는 것은 나쁩니다).


erase()메서드는 삭제 된 요소 뒤의 다음 요소를 가리키는 새 (유효한) 반복기를 반환합니다. 이 반복자를 사용하여 루프를 계속할 수 있습니다.

std::vector<std::string>::iterator iter;
for (iter = m_vPaths.begin(); iter != m_vPaths.end(); ) {
    if (::DeleteFile(iter->c_str()))
        iter = m_vPaths.erase(iter);
    else
        ++iter;
}

파일을 지울 시간이 주어지면 문제가되지 않지만 벡터를 거꾸로 반복하는 것이 좋습니다. 일반적으로 벡터의 끝에서 항목을 삭제하는 방식입니다. 항목을 삭제하는 데 걸리는 시간은 벡터에서 항목 뒤에 오는 항목 수에 비례합니다. 예를 들어 100 개의 파일 이름으로 구성된 벡터가 있고 모두 성공적으로 삭제 한 경우 프로세스에서 마지막 요소를 100 번 복사하고 두 번째 요소를 마지막 요소에 99 번 복사하는 식입니다.

OTOH, if you start from the end and work backwards, you don't copy as long as deleting the files is successful. You can use reverse iterators to traverse the vector backwards without changing much of anything else. For example, GMan's code using remove_if should continue to work (only a tad faster) simply by substituting rbegin() for begin(), and rend() for end.

Another possibility is to use a deque instead of a vector -- a deque can erase items from the end or the beginning of the collection in constant time.

참고URL : https://stackoverflow.com/questions/1604588/iterate-vector-remove-certain-items-as-i-go

반응형