简体   繁体   English

使用STL按成员订购容器

[英]Order a container by member with STL

Suppose I have some data stored in a container of unique_ptr s: 假设我有一些数据存储在unique_ptr的容器中:

struct MyData {
    int id;  // a unique id for this particular instance
    data some_data; // arbitrary additional data
};

// ...

std::vector<std::unique_ptr<MyData>> my_data_vec;

The ordering of my_data_vec is important. my_data_vec的顺序很重要。 Suppose now I have another vector of IDs of MyDatas: 假设我现在有另一个ID为MyDatas的向量:

std::vector<int> my_data_ids;

I now want to rearrange my_data_vec such that the elements are in the sequence specified by my_data_ids . 我现在想要重新排列my_data_vec ,使得元素按照my_data_ids指定的顺序my_data_ids (Don't forget moving a unique_ptr requires move-semantics with std::move() .) (不要忘记移动unique_ptr需要使用std::move()移动语义。)

What's the most algorithmically efficient way to achieve this, and do any of the STL algorithms lend themselves well to achieving this? 什么是实现这一目标的最具算法效率的方法,并且任何STL算法都能很好地实现这一目标吗? I can't see that std::sort would be any help. 我看不出std::sort会有任何帮助。

Edit: I can use O(n) memory space (not too worried about memory), but the IDs are arbitrary (in my specific case they are actually randomly generated). 编辑:我可以使用O(n)内存空间(不太担心内存),但ID是任意的(在我的特定情况下,它们实际上是随机生成的)。

  1. Create a map that maps ids to their index in my_data_ids . 创建一个映射,将id映射到my_data_ids的索引。
  2. Create a function object that compares std::unique_ptr<MyData> based on their ID's index in that map. 创建一个函数对象,根据该映射中的ID索引比较std::unique_ptr<MyData>
  3. Use std::sort to sort the my_data_vec using that function object. 使用std::sort来使用该函数对象对my_data_vec进行排序。

Here's a sketch of this: 这是一个草图:

// Beware, brain-compiled code ahead!
typedef std::vector<int> my_data_ids_type;
typedef std::map<int,my_data_ids_type::size_type> my_data_ids_map_type;

class my_id_comparator : public std::binary_function< bool
                                                    , std::unique_ptr<MyData>
                                                    , std::unique_ptr<MyData> > {
public:
  my_id_comparator(const my_data_ids_map_type& my_data_ids_map)
    : my_data_ids_map_(my_data_ids_map) {}

  bool operator()( const std::unique_ptr<MyData>& lhs
                 , const std::unique_ptr<MyData>& rhs ) const
  {
     my_data_ids_map_type::const_iterator it_lhs = my_data_ids_map_.find(lhs.id);
     my_data_ids_map_type::const_iterator it_rhs = my_data_ids_map_.find(rhs.id);
     if( it_lhs == my_data_ids_map_.end() || it_rhs == my_data_ids_map_.end() )
       throw "dammit!"; // whatever
     return it_lhs->second < it_rhs->second;
  }
private
  my_data_ids_map_type& my_data_ids_map_;
};

//...

my_data_ids_map_type my_data_ids_map;
// ...
// populate my_data_ids_map with the IDs and their indexes from my_data_ids
// ...
std::sort( my_data_vec.begin(), my_data_vec.end(), my_id_comparator(my_data_ids_map) );

If memory is scarce, but time doesn't matter, you could do away with the map and search the IDs in the my_data_ids vector for each comparison. 如果内存不足,但时间无关紧要,您可以取消地图并搜索my_data_ids向量中的ID以进行每次比较。 However, you would have to be really desperate for memory to do that, since two linearly complex operations per comparison are going to be quite expensive. 但是,你必须非常渴望内存才能做到这一点,因为每次比较的两个线性复杂操作将非常昂贵。

Why don't you try moving the data into a STL Set ? 为什么不尝试将数据移动到STL集中? you need only to implement the comparison function, and you will end up with a perfectly ordered set of data very fast. 你只需要实现比较功能,你最终会得到一组完美有序的数据。

为什么不直接使用map<int, unique_ptr<MyData>> (或multimap )?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM