从std :: vector获取特定结构对象的快速方法

时间:2013-08-29 15:49:19

标签: c++ c++11 vector struct

我有一个名为struct的简单Item

struct Item {
    unsigned int id;
    std::string name;

    Item() : id( 0 ), name( std::string( "" ) ) {

    };
};

然后我让这个班级来容纳所有这些Item

class ItemData {
public:
    std::vector< Item > m_Items;
private:
    void load() {
         // Parse a JSON string to fill up m_Items vector with
         // Item objects.
    }

    const Item getItem( unsigned int pID ) {
        // Create an "empty" Item object with ID = 0 and name = ""
        Item temp = Item();

        // Loop through the vector
        for ( unsigned int i = 0; i < m_Items.size(); i++ ) {
            // Check if the current Item object has the id we are looking for
            if ( m_Items.at( i ).id == pID ) {
                // The item is inside the vector, replace temp with the
                // target vector
                temp = m_Items.at( i );

                // Stop looping
                break;
            }
        }

        // If pID was found, temp will have the values of the object inside the vector
        // If not, temp will have id = 0 and name = ""
        return temp;
    }
};

我觉得这个方法需要花费太多时间,特别是如果在循环中调用了ItemData::getItem(unsigned int)

是否有更有效的方法在矢量中获取对象而不通过矢量循环?我应该使用不同的容器(例如std::list)吗?

4 个答案:

答案 0 :(得分:4)

改为使用std::map

class ItemData {
public:
    std::map<unsigned, Item> m_Items;
private:
    void load() {
         // Parse a JSON string to fill up m_Items vector with
         // Item objects.
    }

    const Item getItem(unsigned id) const {
        std::map<unsigned, Item>::const_iterator it = m_Items.find(id);
        if (it != m_Items.end())
            return it->second;
        return Item();
    }
};

您也可以考虑std::unordered_map

答案 1 :(得分:4)

如果您只想迭代容器中的所有项目,那么矢量就很棒。如果您在相对不频繁的情况下进行线性搜索与性能无关,那么矢量可能仍然可以。

如果您需要能够按ID查找项目并且不关心保留容器中项目的插入顺序,那么请使用mapunordered_map取决于您的分拣需求,容器大小等。

如果你需要保持插入顺序按id 进行快速查找,你将不会从向量中删除项目,那么我会建议{{ 1)用于索引的id,并在添加新项时保持id-index映射。

答案 2 :(得分:2)

绝对不是std::list。我相信您正在寻找std::map(将唯一ID映射到对象)。或者std::set(只存储唯一对象)和自定义比较器,以便Item根据id进行比较。

set会将对象存储为const。我相信map最适合您(将id存储一次作为地图密钥并且在Item内部的费用很低)。

答案 3 :(得分:0)

  

我想保留插入顺序以及快速查找,但可能不需要删除项目

所以你想要的是为矢量做一个索引。这是创建一个哈希表,将项目ID映射到向量中的项目位置:

class ItemData {
    vector< Item > m_Items;
    unordered_map<unsigned int, size_t> m_ItemsIndex;

    void prepare_index()
    {
        for (size_t i = 0; i < m_Items.size(); i++)
           m_ItemsIndex[m_Items[i].id] = i;
    }

    Item& get_item(unsigned int id)
    {
        size_t pos = m_ItemsIndex[id];
        return m_Items[pos];
    }
}

这提高了从线性(O(n))到恒定时间(O(1))的查找速度。

prepare_index结束时致电load。您还需要添加错误检查等,但您明白了。

保留插入顺序,因为您仍然可以直接迭代向量。