我想访问/遍历unordered_multimap中的所有非唯一键。
哈希表基本上是来自签名<SIG>
的映射,其实际上在实践中确实出现多次到标识符<ID>
。我想在哈希表中找到那些出现一次的条目。
目前我使用这种方法:
// map <SIG> -> <ID>
typedef unordered_multimap<int, int> HashTable;
HashTable& ht = ...;
for(HashTable::iterator it = ht.begin(); it != ht.end(); ++it)
{
size_t n=0;
std::pair<HashTable::iterator, HashTable::iterator> itpair = ht.equal_range(it->first);
for ( ; itpair.first != itpair.second; ++itpair.first) {
++n;
}
if( n > 1 ){ // access those items again as the previous iterators are not valid anymore
std::pair<HashTable::iterator, HashTable::iterator> itpair = ht.equal_range(it->first);
for ( ; itpair.first != itpair.second; ++itpair.first) {
// do something with those items
}
}
}
这肯定是无效的,因为外部循环遍历散列表的所有元素(通过ht.begin()
),内部循环测试相应的键是否存在多次。
有更高效或更优雅的方法吗?
注意:我知道使用unordered_map
代替unordered_multimap
我不会遇到此问题,但由于应用程序要求,我必须能够存储指向不同的多个密钥<SIG>
标识符<ID>
。另外,unordered_map<SIG, vector<ID> >
对我来说不是一个好选择,因为它使用了大约150%的内存,因为我有许多唯一的密钥,vector<ID>
为每个项目增加了相当多的开销。
答案 0 :(得分:2)
使用std::unordered_multimap::count()
确定具有特定密钥的元素数量。这为您节省了第一个内循环。
您无法阻止对整个HashTable
进行迭代。为此,HashTable
必须维护第二个索引,将基数映射到键。这将引入显着的运行时和存储开销,并且仅在少数情况下有用。
您可以使用std::for_each()
隐藏外部循环,但我认为这不值得。
答案 1 :(得分:0)
我认为您应该将数据模型更改为:
std::map<int, std::vector<int> > ht;
然后您可以轻松地迭代地图,并检查每个元素包含size()
但在这种情况下,构建数据结构并以线性模式读取它会稍微复杂一些。