【问题标题】:Automatic Clustering With Hash/Map of Vectors in C++在 C++ 中使用向量的哈希/映射进行自动聚类
【发布时间】:2011-01-02 09:20:02
【问题描述】:

例如,我有以下值:

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;
}

【问题讨论】:

    标签: c++ data-structures hash map vector


    【解决方案1】:

    您每次插入时都会覆盖向量。你可以做的是:

    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);
    }
    

    【讨论】:

      【解决方案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 的参考,既漂亮又干净。

      【讨论】:

        【解决方案3】:

        你做错的是每次都重写地图中的向量。

        代替:

        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 );
        }
        

        【讨论】:

        • 我忍不住发出 map::insert(value_type) 返回迭代器的信号,因此您可以在 if 块内分配给 iter 并且只有一次 -&gt;second.push_back(TagId) 位(并且没有 @987654328 @ 子句)......但这可能是挑剔的:P
        【解决方案4】:

        这个怎么样?而不是你的CCTagMap,定义:

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

        然后为每个TagIdCcId 做:

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

        【讨论】:

          猜你喜欢
          • 2012-08-29
          • 2013-07-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-23
          • 1970-01-01
          • 1970-01-01
          • 2015-09-21
          相关资源
          最近更新 更多