2013-04-18 2 views
1

훨씬 큰 프로그램의 일부로 벡터에있는 모든 동일한 문자열 수의 출력을 얻으려고합니다. 많은 연구가 끝난 후에 나는 함께 작동하는 것을 만들었지 만 그것은 더러워 보입니다. 그리고 더 나은 방법이 있는지 궁금합니다.벡터에서 동일한 문자열을 쉽게 계산할 수 있습니까?

#include <vector> 
#include <string> 
#include <map> 
#include <algorithm> 
#include <iostream> 

using namespace std; 

void setMap(string i); 
void addMap(string i); 
map<string, int> myMap; 

int main() 
{ 
    vector<string> myVector; 
    string myArray[6]={"foo","foo","bar","roo","foo","bar"}; 
    for (int i=0; i<6; i++) 
    { 
     myVector.push_back(myArray[i]); 
    } 
    for_each (myVector.begin(), myVector.end(), setMap); 
    for_each (myVector.begin(), myVector.end(), addMap); 
    for (map<string, int, less<string>>::const_iterator iter = myMap.begin(); 
     iter != myMap.end(); ++iter) 
     cout <<iter->first<<'\t'<<iter->second<<endl; 
    return 0; 
} 

void setMap(string i) 
{ 
    myMap[i]=0; 
} 

void addMap(string i) 
{ 
    myMap[i]++; 
} 

이 코드는 잘 작동하고 나에게 난 후였다 출력을 제공하지만 그것이 작동되도록하는 2 개 여분의 기능을 추가 할 필요하거나지도가 글로벌하게하는 데에 그 치열하지 않다. 어떤 힌트라도 기꺼이 받아 들여질 것입니다.

+0

C++ 03 또는 C++ 11? – leemes

+0

'for_each'를 사용하려면 맵에 대한 참조를 보유하도록 설계된 * functor *를 사용하여 코드를 제거하면됩니다. [라이브보기] (http://ideone.com/ZbMU8r). * lambda *를 사용하여 * 더 * 컴팩트하게 만들 수도 있습니다. [그것을 보아라.] (http://ideone.com/H59HHM). – WhozCraig

답변

4

추가 기능이없고 전역으로 맵을 가지지 않는 가장 간단한 방법은 for_each를 사용하지 않는 것입니다. 당신은 또한 맵 값 어쨌든 제로로 초기화되기 때문에 첫 번째 루프

map<string, int> myMap; 
for (vector<string>::iterator i = myVector.begin(); i != myVector.end(); ++i) 
    ++myMap[*i]; 

을 제거 할 수 있음을 완료하면

for_each (myVector.begin(), myVector.end(), setMap); 
for_each (myVector.begin(), myVector.end(), addMap); 

map<string, int> myMap; 
for (vector<string>::iterator i = myVector.begin(); i != myVector.end(); ++i) 
    myMap[*i]=0; 
for (vector<string>::iterator i = myVector.begin(); i != myVector.end(); ++i) 
    ++myMap[*i]; 

된다.

어쨌든 for_each를 사용해야한다고 생각하게 된 이유는 무엇입니까?

+0

C++의 새로운 기능, 일반적으로 일반적인 프로그래밍입니다. 그것은 내가 벡터에서 그렇게 많은 경험을하지 않았고 이전에지도를 사용 해본 적이없는 것처럼 나에게 의미가있는 것처럼 보였다. 내가하고있는 프로젝트는 엄청난 학습 곡선이며이 사이트는 많은 도움이되었습니다. – Modred

+0

for_each는 for 루프 IMHO의 더 어색한 버전이며 거의 쓰지 않습니다. – john

+0

완벽하게 작동합니다 (a를 제외하고, 우리 모두가 오타를 만들어야합니다.). 더 나은 해결책을 요구하지 못했습니다. – Modred

3

어떨까요? 재사용을 위해 별도의 함수로 계수 메커니즘을 캡슐화합니다.

// Iterator pair based interface 
template <class Iterator> 
std::map<typename Iterator::value_type,int> 
count(Iterator begin, Iterator end) { 
    std::map<typename Iterator::value_type,int> counts; 
    for (Iterator i = begin; i != end; ++i) 
     counts[*i]++; 
    return counts; 
} 

// Sequence interface 
template <class Sequence> 
inline std::map<typename Sequence::value_type,int> 
count(Sequence seq) { 
    return count(seq.begin(), seq.end()); 
} 

그럼 간단하게 다음과 같이 사용 :

// C++11 
for (const auto & c : count(myVector)) 
    cout << c->first << '\t' << c->second << endl; 

// C++03 
std::map<string,int> counts = count(myVector); 
for (std::map<string,int>::const_iterator c = counts.begin(), e = counts.end(); c != e; ++c) 
    cout << c->first << '\t' << c->second << endl; 

Simple demo

+0

당신은'template std :: map 을 필요로합니다. sequence :: value_type, int> count (시퀀스 seq) {return count (seq.begin(), seq.end()) ;}'. –

+0

기본 템플릿 인수도 C++ 11임을 확인했습니다. 젠장, 나는 그것에 익숙해있다;) – leemes

+0

좋아, 이제는 그것을 고쳤다. – leemes

3

귀하의 setMap 기능이 필요하지 않습니다.

지도의 키가 없으면이 기능의 역할을 고려하십시오.

void addMap(string i) 
{ 
    myMap[i]++; 
} 

표현식 myMap[i]은지도에 새 키를 추가합니다.

값 유형이 int이므로이 새로운 값은 0이 될 것이므로 int()이됩니다.

2

C++ 11에서, 당신은이 작업을 수행 할 수 있습니다

#include <string> 
#include <unordered_map> 
#include <iostream> 

int main() { 

    std::string myArray[6] = {"foo","foo","bar","roo","foo","bar"}; 

    std::unordered_map<std::string, size_t> m; 
    for (const auto& s : myArray) 
     ++m[s]; 

    for (const auto& p : m) 
     std::cout << p.first << "\t" << p.second << std::endl; 

} 

이 인쇄되지 않은 : 이미있는 경우 m[s] 자동 ms를 삽입하기 때문에

foo  3 
bar  2 
roo  1 

이 작동합니다.

std::unordered_map (해시 테이블)을 사용하면 std::map (균형 트리)보다 저렴할 수 있습니다. 당신은 위 루프 "각"루프 "를"정규로 대체 될 것이다 제외하고 C++ 03에서 매우 비슷한 일을 할 수


.

0
#include <iostream> 
#include <string> 
#include <vector> 
#include <iterator> 
#include <map> 

using namespace std; 

int main (int argc, char * const argv[]) { 

    string myArray[]={"foo","foo","bar","roo","foo","bar"}; 
    int arr_length = 6; 
    vector<string> myVector(myArray, myArray + arr_length); 

    //Print contents of vector: 
    copy(myVector.begin(), 
     myVector.end(), 
     ostream_iterator<string>(cout, " ") 
    ); 

    cout << endl; 



    map<string, int> myMap; 

    vector<string>::iterator pos; 
    for (pos=myVector.begin(); pos<myVector.end(); ++pos) 
    { 
     myMap[*pos] += 1; 
    } 

    map<string, int>::iterator mapPos; 
    for (mapPos=myMap.begin(); mapPos != myMap.end(); ++mapPos) { 
     cout << "word: " << mapPos->first << "\t" 
      << "count: " << mapPos->second << endl; 
    } 




     return 0; 
} 


--output:-- 
foo foo bar roo foo bar 
word: bar count: 2 
word: foo count: 3 
word: roo count: 1 
관련 문제