2009년 03월 01일
STL 맵을 이용하여 벡터의 중복 된 데이터 제거하기

데이터를 다루다 보면 벡터에 중복 된 데이터를 제거해야 할 경우가 발생합니다. 중복 된 데이터를 제거하는 방법이야 여러가지가 있겠지만 STL 맵을 이용하여 중복 된 데이터를 제거하는 방법에 대해서 알아보겠습니다.

먼저, 상황을 아래와 같이 만들어 보았습니다. 아래 배열 x1과 x2의 각 인덱스의 값은 서로 쌍으로 이용됩니다. 즉, x1[0]과 x2[0]의 값이 서로 쌍으로 이용됩니다. 이 경우 (x1[0], x2[0])의 값과 (x1[1], x2[1])의 값은 서로 중복 되므로 (x1[0], x2[0])의 값만 남기고 (x1[1], x2[1])의 값은 버리려고 합니다. 이때, STL  맵을 이용하여 중복 된 데이터를 제거한 후 남긴 데이터를 벡터에 담아 보도록 하겠습니다.


double x1[] = {-1.00, -1.00, -1.00, -1.00, -0.33, -0.33, 0.33, 0.33, 1.00, 1.00, 1.00, 1.00};
double x2[] = {-0.89, -0.89, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.89, 0.89};


STL 맵 중 멀티 맵이 아닌 일반 맵은 중복 Key를 허용하지 않습니다. 즉, 같은 Key의 데이터를 삽입하려고 하면 삽입이 되지 않지요. 이 원리를 이용하면 위 배열의 중복 된 값을 쉽게 제거할 수 있습니다. (x1[0], x2[0])의 데이터를 문자열로 변환 후 이 값을 키로 만듭니다. 예를 들어 "-1.00#-0.89" 처럼 말이죠. 이때, 반드시 중간에 '#'과 같은 구분자를 주도록 합니다. 이렇게 구분자를 넣어주는 이유는 0.0이란 값과 10이란 값을 위의 방법으로 문자열로 변환 하는 경우 "0.010"이란 값이 나옵니다. 그런데 0.01이란 값과 0이란 값 또한 위 방법으로 문자열로 변환하면 "0.010"이 됩니다. 이럴 경우를 대비하여 각 값 간 사이에 구분자를 꼭 붙여주도록 합니다. 이렇게 Key를 만들었으면 값으로 현재 배열의 index를 줍니다. 그럼 중복 되는 값의 배열 index는 제외한 체 map에 삽입이 되게 됩니다. 그 후 맵을 순회 하면서 map의 저장 된 value 즉, 배열의 index를 각 배열에 적용하여 중복 된 데이터의 첫번째 값만 빼내어 vector에 담습니다.

위 설명을 그림으로 표현하면 아래와 같습니다.


위 설명을 소스로 구현해 보았습니다.


// RepeatDataFilter.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <map>
#include <vector>
#include <string>

using namespace std;

template<typename T>
void RepeatDataFilter(const vector<T>& arg_refVtrInX1, const vector<T>& arg_refVtrInX2, vector<T>& arg_refVtrOutX1, vector<T>& arg_refVtrOutX2)
{
 map<string, int> mFilter;
 TCHAR szBuf[100];

 int nSize = (int) arg_refVtrInX1.size();
 for(int i=0; i<nSize; i++)
 {
  memset(szBuf, 0, sizeof(TCHAR));

  _stprintf(szBuf, _T("%f#%f"), arg_refVtrInX1[i], arg_refVtrInX2[i]);
  pair<string, int> item(szBuf, i);
 
  mFilter.insert(item);
 }

 map<string, int>::iterator it;
 for(it = mFilter.begin(); it != mFilter.end(); it++)
 {
  arg_refVtrOutX1.push_back(arg_refVtrInX1[it->second]);
  arg_refVtrOutX2.push_back(arg_refVtrInX2[it->second]);
 }
}

int _tmain(int argc, _TCHAR* argv[])
{
 double x1[] = {-1.00, -1.00, -1.00, -1.00, -0.33, -0.33, 0.33, 0.33, 1.00, 1.00, 1.00, 1.00};
 double x2[] = {-0.89, -0.89, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.89, 0.89};

 vector<double> vtrInitX1, vtrInitX2;
 vector<double> vtrX1, vtrX2;

 int nArr = (int) (sizeof(x1) / sizeof(double));

 for(int i=0; i<nArr; i++)
 {
  vtrInitX1.push_back(x1[i]);
  vtrInitX2.push_back(x2[i]);
 }

 RepeatDataFilter<double>(vtrInitX1, vtrInitX2, vtrX1, vtrX2);

 TRACE(_T("\n\n=========================================================\n\n"));
 size_t nSize = vtrX1.size();
 for(size_t i=0; i<nSize; i++)
 {
  TRACE(_T("\n%5.2f\t%5.2f"), vtrX1[i], vtrX2[i]);
 }
 TRACE(_T("\n\n=========================================================\n\n"));

 return 0;
}



*결과



=========================================================


-0.33  0.00
-1.00 -0.89
-1.00  0.00
 0.33  0.00
 1.00  0.00
 1.00  0.89

=========================================================


* 예제 프로젝트

    RepeatDataFilter.zip
by greenfrog | 2009/03/01 14:33 | C++ / WIN32 / MFC | 트랙백 | 덧글(0)
트랙백 주소 : http://greenfrog7.egloos.com/tb/1389475
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글



<< 이전 페이지 | 다음 페이지 >>