2010-01-07 44 views
0

我具有例如下列值:自動聚類隨着散列/地圖載體的在C++

0 0 0 1 3 2 

這些值是指簇ID,其中,集羣的成員是向量的 索引。因此,我們希望得到這種輸出:

Cluster 0 -> 0,1,2 
Cluster 1 -> 3 
Cluster 2 -> 5 
Cluster 3 -> 4 

我嘗試了以下構造,但它似乎並沒有工作: 什麼是做到這一點的呢?

#include <iostream>  
#include <vector>   
#include <fstream> 
#include <sstream> 
#include <map> 
using namespace std; 

int main (int arg_count, char *arg_vec[]) { 
    if (arg_count !=2) { 
     cerr << "expected one argument" << endl; 
     return EXIT_FAILURE;  
    } 

    string line; 
    ifstream myfile (arg_vec[1]); 

    map <int, vector <int> > CCTagMap; 

    if (myfile.is_open()) 
    { 
     // Skip First Line   
     getline(myfile,line);  

     while (getline(myfile,line)) 
     { 
      stringstream ss(line);  
      int CcId; 
      int TagId = -1;   



      vector <int> Temp;   

      while (ss >> CcId) {  
       TagId++; 
       cout << CcId << "-" << TagId << endl; 

       # this way to cluster doesn't seem to work 
       CCTagMap.insert(make_pair(CcId,Temp.push_back(TagId))); 
      } 


     } 
     myfile.close(); 
    } 
    else { cout << "Unable to open file\n";} 
    return 0; 
} 

回答

1

你做錯了什麼是每次都在地圖上重寫向量。

相反的:

CCTagMap.insert(make_pair(CcId,Temp.push_back(TagId))); 

嘗試:

if (CCTagMap.find(CcId) == CCTagMap.end()) 
{ 
    CCTagMap.insert(make_pair(CcId,vector<int>())); 
} 
CCTagMap[CcId].push_back(TagId); 

甚至更​​好,

map <int, vector<int> >::iterator iter = CCTagMap.find(CcId); 
if (iter == CCTagMap.end()) 
{ 
    CCTagMap.insert(make_pair(CcId,vector<int>())).first->second.push_back(TagId); 
} 
else 
{ 
    iter->second.push_back(TagId); 
} 
+0

我不禁發出信號,說明'map :: insert(value_type)'返回迭代器,所以你可以在'if'塊中指定'iter',只有一次''> second.push_back (TagId)'位(並且沒有'else'子句)...但是這可能是挑剔的:P – 2010-01-07 18:53:20

2

您在插入過程中,每次覆蓋載體。你可以做的是這樣的:

map <int, vector <int> >::iterator iter = CCTagMap.find(CcId); 
if(iter == CCTagMap.end()) 
{ 
    vector <int> Temp; 
    temp.push_back(TagId); 
    CCTagMap[CcId] = temp; 
} 
else 
{ 
    iter->second.push_back(TagId); 
} 
1

這個怎麼樣?而不是你CCTagMap的,定義:

std::vector<std::vector<int> > clusters; 

然後爲每個TagIdCcId做:

if (clusters.size() <= CcId) 
    clusters.resize(CcId + 1); 
clusters[CcId].append(TagId); 
2

我以爲我會發布的解決方案去爲性能(記住,你應該總是嘗試將盡快優化儘可能根據Knuth!除非我錯了;))。

CCTagMap[CcId].push_back(TagId); 

呀,我真的認爲我應該指出這種解決方案

  • 節省一些打字
  • 更好的性能:只有一個查詢,而不是一個用於查找和一個用於插入。沒有暫時的(儘管他們可能會被優化)。
  • 慣用?

對於什麼是怎麼回事的分解圖:

std::vector<int>& CcVector = CcTagMap[CcId]; // [1] 
CcVector.push_back(TagId);     // [2] 
  1. map::operator[]是不同誘變操作:它返回或儲存用於該鍵的元素或者如果沒有存在插入一個新的默認構造的元素。然後它返回元素的引用(不管是否新建)。
  2. 我們使用的參考爲直接push_back,很乾淨。
+0

+1:絕對是使用地圖的慣用方式 – 2010-01-08 09:07:00