【问题标题】:Quickly get an element from vector2 given an element from vector1给定vector1中的元素,快速从vector2中获取一个元素
【发布时间】:2013-10-28 11:39:46
【问题描述】:

我有两个向量vector<DataPoint> datavector<string> labels,其中DataPoint 只是一个浮点向量:typedef vector<float> DataPoint。每个数据点data[i] 都有其关联的标签labels[i]

有什么方法可以快速获取给定数据点x 的标签? string getLabel(DataPoint x){..} 之类的东西很快。

【问题讨论】:

  • “快”是什么意思?
  • @ForEveR 我的意思是,不浏览向量data 是为了搜索x 的索引i,然后标签是labels[i]。这并不快。
  • @shn:我想你的意思是:DataPoint 只是一个浮点向量,不是吗?
  • @lolando 是的,我认为typedef vector<float> DataPoint 很清楚
  • This thread 可能会有所帮助:散列每个浮点向量,然后将与labels[i] 关联的每个结果值hash(data[i]) 插入std::unordered_map<size_t, TYPE_OF_LABELS>,如table[hash(data[i])] = labels[i]。这将授予您O(1) 搜索。

标签: c++ vector


【解决方案1】:

如果您的data 向量已排序,您希望在data 中找到DataPoint 的最佳索引是O(log(n)) 复杂度(使用二进制搜索)。否则,这是O(n) 中的线性搜索。

问题的症结在于您有两个包含相关数据的向量,这总是很难管理(并且强烈暗示设计不佳)。最好用 vector<LabeledDataPoints> 替换这两个向量(具有两个成员的结构:DataPointstring)。

【讨论】:

  • 排序? data 是浮点向量的向量,不能“排序”。例如,在 python 中,如果我创建一个将数据与标签相关联的字典,我可以在 O(1) 中搜索给定数据点的标签。我不知道如何在 C++ 中做到这一点。
  • @shn:那是因为 python 中的字典更像 C++ 中的 std::unordered_map
  • @shn 绝对没有理由不能对其进行排序。无论如何,您所描述的是std::map(或unordered_map)而不是vector。您还必须为DataPoint 提供一个哈希函数。尽管如此,我仍然坚持我的建议,即包含 LabeledDataPoint 结构的单个向量。
  • @shn 那么请通过编辑在您的问题中明确说明。据我了解,您要求在vector 中进行 O(1) 检索,这是不可能的。在您进行编辑后,我将删除我的答案,因为它将变得无关紧要。
  • syam:“包含 LabeledDataPoint 结构的单个向量” - 这与问题正交......一旦知道索引,发现标签无论如何都是 O(1)。是否对向量进行排序或移动到另一个数据结构是有意义的问题。无论如何,O(log2N) 已经足够快了,除非另有证明,而且你提到了排序,所以我 +1。
【解决方案2】:

一些注意事项:可以用std::sort()对向量进行排序,用std::binary_search()搜索预排序的向量,std::unordered_map是C++11哈希表,std::map是二叉树,您可以使用 O(log2N) 查找、插入和擦除进行插入时间排序。谷歌其中任何一个文档。

使用您现有的数据结构,如果 dataPoint 是预先排序的,那么您有 O(log2N),其中 N 是 dataPoint.size(),并假设 平均不相等的 dataPoints 比较只需要比较第一个浮点数或两个。未排序,为 O(N)。

显然,性能问题是不必在已知公共索引后查看标签 - 它只是找出该索引是什么,给定 data 向量之外的 dataPoint 对象。

如果排序不理想或 O(log2N) 仍然太慢,您可以考虑将数据点放入带有标签的哈希表中。

在不太可能的情况下,性能问题仅是由于您的 dataPoints 经常以相同的浮动前导序列开始,那么(假设没有简单的解决方案,例如从向量的背面到前面进行比较),您可以创建某种首先比较元素的哈希值或总和,如果已知相等,则仅进行逐个浮点数比较。

【讨论】:

    【解决方案3】:

    旧答案(它是关于轻松获取值(DataPoint 实例)):


    你为什么不使用地图,使用标签作为键和数据点作为值(地图)?通过这种方式,您将拥有关联的数据,并且根据地图类型,您可以对复杂性进行区分(使用地图,查找复杂度为 O(logn),而哈希图的预期复杂度为 O(1),并且O(n) 最坏情况)。使用对您更有效的方法。 有关地图及其复杂性的更多信息,请查看此处:multiset, map and hash map complexity


    更新:

    要获取每个 DataPoint 的标签,一个想法是创建一个单独的类(例如 DataContainer),其中包含作为私有成员的 DataPoint 实例向量和一个字符串,其中包含您的标签和适当的 setter/getter。

    class DataContainer{
      private:
        DataPoint mDataPoint;
        string mLabel;
    
      public:
        DataContainer(DataPoint dataPoint,string label): 
          mDataPoint(dataPoint), mLabel(label){}
    
        void setDataPoint(DataPoint dataPoint){
          mDataPoint = dataPoint;
        }
    
        void setLabel(string label){
          mLabel = label;
        }
    
        DataPoint getDataPoint(){
          return mDataPoint;
        }
    
        //This getter does the job, with O(1) complexity.
        string getLabel(){
          return mLabel;
        }
      }
    

    这样,您可以将您的 DataContainer 放在您想要的任何结构中(如果您想类似地获取键,我建议使用 map:map),在实例化时设置标签并使用 getter 方法获取它 O( 1) 复杂性。 如您所见,您的问题需要以不同的方式处理,并且有一些方法可以做到。

    【讨论】:

    • 我有vector< vector<floats> > datavector<strings> label; 给定的用户给我发一个数据:vector<float> x,我应该把对应的标签返回给他。所以 Map 不能成立。 unordered_map<vector<floats>, int> 可以很方便,但我不会用 C++11
    • 或者只是 map, string> 我猜会起作用。
    • map的使用方式是map。所以,你可以做 map>。我认为 STL 中的地图 API 让您有机会使用带有 get 方法的键来检索值。 cplusplus.com/reference/map/map
    • 通过检索值,您将浏览它们以搜索您想要的值并获取相应的字符串键。同样的问题..
    • 答案已更新。请检查一下。
    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 2014-09-22
    • 2015-08-09
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    相关资源
    最近更新 更多