2014-05-20 4 views
1

괜찮습니다. 다른 (더 간단하지만 충분하지는 않지만 설명이 충분하지 않은) 질문을 위해, 이것이 가능하거나 불가능한 것인지 묻지는 않습니다. (이미 알아 냈기 때문에), 저보다 가벼운 대안이 있는지 묻고 있습니다. 문제.C++ 11 for for 루프가있는 벡터에서 지울 수 있습니까?

내가 가진 것은 메인 클래스로 간주 될 것이고, 그 메인 클래스에는 '월드 맵'클래스를 참조하는 변수가 있습니다. 본질적으로이 'WorldMap'클래스는 다른 클래스 변수의 컨테이너입니다. 메인 클래스는 모든 루핑을 수행하고 활성화 된 각 객체를 모두 업데이트합니다. 이 루프에는 반복적 인 컨테이너 집합 내부의 벡터 객체를 삭제해야하는 경우가 있습니다 (제공된 코드 참조). 그것은 반복적으로 반복적으로 다른 포인터 (및 등)에 필요한 개체를 가리키는 포인터로 필요한 변수를 참조해야 나중에 지울 것입니다 (이것은 C++로 전환하기 전에 사용한 개념이었습니다.) 11) 그래서 대신 루프에 대한 범위가 있습니다 (코드에도 표시됨). 예제 코드는 내가 지루함을 줄이고 코드를 훨씬 더 읽기 쉽도록 만들고 싶다는 생각을 보여줍니다.

struct item{ 
    int stat; 
}; 

struct character{ 
    int otherStat; 
    std::vector<item> myItems; 
}; 

struct charContainer{ 
    std::map<int, character> myChars; 
}; 

int main(){ 
    //... 
    charContainer box; 
    //I want to do something closer to this 
    for(item targItem: box.myChars[iter].myItems){ 
     //Then I only have to use targItem as the reference 
     if(targItem.isFinished) 
      box.myChars[iter].myItems.erase(targItem); 
    } 
    //Instead of doing this 
    for(int a=0;a<box.myChars[iter].myItems.size();a++){ 
     //Then I have to repeatedly use box.myChars[iter].myItems[a] 
     if(box.myChars[iter].myItems[a].isFinished) 
      box.myChars[iter].myItems.erase(box.myChars[iter].myItems[a]); 
    } 
} 

TLDR :

은 예제 코드 나는 반복 C++ 11과 같이 루프에 대한 새 범위를 사용하여 전체 참조를 호출하는 지루함을 제거 할.

EDIT : 요소를 모두 한꺼번에 삭제하려고하지 않습니다. 첫 번째 루프에서 어떻게 삭제할 것인지 묻습니다. 내가 그들을 (ex 문을 통해) 외부 적으로 끝낼 때 삭제하고있다. 모든 요소가 아닌 특정 요소를 어떻게 삭제합니까?

+0

내가 그랬다면 누군가 걸어 들어가서 "너가 무엇을 묻고 시도하는지 모르겠다!"라고 말할 수있는 좋은 기회가되었습니다. – Molma

+1

글쎄, 패딩없이 자연스러운 답변 (구조체와 같은)과 정보를 변경할 수 없다는 것을 분명히 알 수 있습니다 ... 괜찮습니다.하지만 짧음. 다른 말로하면 짧은 질문만으로도 설명을 요청할 수 있지만 긴 질문은 무시 될 수 있습니다. –

+0

이것은 당신의주의를 꽤 잘 준 것 같습니다 : P. 사람들이 체이스를 즉시 자르고 싶다면 TLDR 메시지도 있습니다. 나는 과거의 경험에 따라 그러한 방식으로 만 포맷하고있다. – Molma

답변

7

당신이 단순히 표준 : : 벡터를 삭제하려면, 당신이 사용할 수있는 아주 간단한 방법이있다 :

std::vector<item> v; 

// Fill v with elements... 

v.clear(); // Removes all elements from v. 

이 외에도, 내가 지적하고자하는 [1] 벡터의 원소를 지우는 것은 반복자의 사용을 필요로합니다. [2] 접근법이 허용 되더라도, for 루프 내부의 벡터에서 원소를 지우는 것은주의하지 않으면 나쁜 생각입니다.

std::vector<int> v = { 1, 2, 3, 4, 5 }; 

그런 다음 루프는 다음과 같은 효과를 가질 것이다 :

  • 첫 번째 반복 :a == 0, size() == 5 가정하여 벡터 5 개 요소가 있습니다. 첫 번째 요소를 제거하면 {2, 3, 4, 5}

  • 두 번째 반복 :a == 1, size() == 4이 포함됩니다.a == 2, size() == 3 : 우리는 다음 벡터 {2,4,5}

  • 세 번째 반복을 포함 할 것이라고 요소를 제거합니다. 세 번째 요소를 제거하고 최종 결과는 {2,4}입니다.

이것은 실제로 벡터를 비우지 않기 때문에 내가 찾은 것이 아닌 것 같습니다.

당신이 요소를 제거하기 위해 적용 할 어떤 특별한 조건이 아닌 경우, 그것은 아주 쉽게 다음과 같은 방법으로 C++ (11)에 적용된다 : 내가 그들을 때를 삭제하고

std::vector<MyType> v = { /* initialize vector */ }; 

// The following is a lambda, which is a function you can store in a variable. 
// Here we use it to represent the condition that should be used to remove 
// elements from the vector v. 
auto isToRemove = [](const MyType & value){ 
    return /* true if to remove, false if not */ 
}; 

// A vector can remove multiple elements at the same time using its method erase(). 
// Erase will remove all elements within a specified range. We use this method 
// together with another method provided by the standard library: remove_if. 
// What it does is it deletes all elements for which a particular predicate 
// returns true within a range, and leaves the empty spaces at the end. 
v.erase(std::remove_if(std::begin(v), std::end(v), isToRemove), std::end(v)); 

// Done! 
+0

빠른 질문 : 어떻게 지우기 루프를 깨뜨릴까요? 예를 들어 나는 다른 곳으로 이동하기위한 무언가 (거리와 재사용 대기 시간 같은 다른 변수의 영향을 받는다)를 찾고있는 루프가 있습니다. 설명에 맞는 첫 번째 발생을 발견하면 루프를 중단합니다. – Molma

+1

다른 표준 라이브러리 알고리즘 인'find_if '로이 작업을 수행 할 수 있습니다. 당신은 아마도 표준 라이브러리에서 제공되는 모든 알고리즘에 대해 읽어야 할 것이다. 당신은 여기에서 그것을 찾을 수 있습니다 : http://www.cplusplus.com/reference/algorithm/ – Svalorzen

2

나는 그들과 함께 외부에서 처리된다 (if 문을 통해). 모든 요소가 아닌 특정 요소를 어떻게 삭제합니까?

내 생각에, 당신은 잘못된 길을보고 있습니다. 시퀀스 컨테이너에서 항목을 삭제하기위한 루프 작성은 항상 문제가 있으므로 권장하지 않습니다. 이런 식으로 항목을 제거하지 않으려 고 노력하십시오.

컨테이너를 사용하여 작업 할 때 전략적으로 코드를 설정하여 삭제되거나 "삭제 예정"항목을 컨테이너에있는 항목에서 쉽게 액세스 할 수있는 컨테이너 부분에 배치해야합니다. 당신은 삭제하고 싶지 않습니다. 당신이 실제로 그것을 제거하고 싶을 때, 당신은 그들이 어디에 있는지 알며, 따라서 컨테이너로부터 그것들을 추방하는 어떤 함수를 호출 할 수 있습니다.

하나의 대답이 이미 주어 졌으므로 erase-remove(if) 관용어를 사용하는 것입니다. remove 또는 remove_if을 호출하면 "불량"인 항목이 컨테이너 끝으로 이동합니다. remove(_if)의 반환 값은 제거 될 항목의 시작에 대한 반복자입니다. 그런 다음이 반복자를 vector::erase 메소드에 제공하여 컨테이너에서 항목을 영구히 삭제합니다.

다른 솔루션 (사용 빈도가 적은)은 std::partition 알고리즘입니다. std::partition도 '나쁜'항목을 컨테이너 끝으로 이동할 수 있지만 remove(_if)과 달리 항목은 계속 유효합니다. 즉, 항목을 컨테이너 끝에두고 안전하게 사용할 수 있습니다. 그런 다음 나중에 std::partition이 반복자를 반환하기 때문에 별도의 단계에서 원하는대로 제거 할 수 있습니다.

+0

이것은 내가 if 문장에서 그것들을 삭제하는 것이 었는지에 대해 꽤 흥미 롭습니다. 나는 더 이상 유용하지 않기 때문에 요소를 무작위로 삭제하는 프로그램 전체에 벡터를 배치했습니다. 이것은 또한 내 질문의 설명에서 설명한 또 다른 상황이다. iteration이 "삭제 플래그가 붙은 것"인지를 확인하기 전에 다른 멤버 함수와 변경 사항 (예 :'targItem-> function1(); targItem-> function2();'등) 의견과 함께. – Molma

+0

내 프로그램은 이미 너무 크기가 크고 모든 프로그램을 추가하면 많은 독자를 화나게 할 수 있습니다. 이것이 내가 예를 든 이유입니다. 이 코드는 실제로 일어나는 것과는 아무런 관계가 없지만 질문의 요점은 쓰여지고 중요하지는 않습니다. 함수에 대한 호출 등이 주석 처리됩니다. 따라서 왜 내 질문에는 혼란이 자주 발생합니까? 나는 또한 (희망적으로 일시적으로) 개인적인 문제로 인해 과도하게 타이핑 할 수 없지만 침대에 머무르는 것은 여름 휴가 (TMI 피하기)에 너무 우울합니다. – Molma

+0

음, 원래 코드는 다음 관용구를 보여줍니다 :'1) 내 벡터를 살펴보십시오. 2) 항목에 일정한 조건이있는 경우 그 내용을 제거한 다음 제거하십시오. '주어진 remove_if/erase'관용구 또는 최소한 '파티션/지우기'관용구입니다. – PaulMcKenzie

0

왜 벡터를 반복하는 표준 반복자가 없습니까? 그렇게하면 반복자를 전달하여 요소를 삭제할 수 있습니다. 그런 다음 .erase()는 사용 가능한 다음 반복자를 반환합니다. 그리고 다음 반복자가 iterator :: end()이면 루프가 종료됩니다.