在其他地图值中查找元素的最佳方法是啥?

Posted

技术标签:

【中文标题】在其他地图值中查找元素的最佳方法是啥?【英文标题】:what's the best way to find the element occurs in other map value?在其他地图值中查找元素的最佳方法是什么? 【发布时间】:2021-02-09 06:28:58 【问题描述】:

我尝试在地图值中找到也出现在其他值中的元素。


  1: ["a", "b", "c", "d"],
  2: ["a", "c"],
  3: ["c", "d"],
  4: ["a", "c"]


=>


  "a": [ 1, 2, 4 ], // a occurs in the map which key are 1/2/4
  "b": [ 1 ],
  "c": [ 1, 2, 3, 4],
  "d": [ 1, 3 ]

我的实现是:

map<int, set<string>> map1 = 
   1, set<string>"a", "b", "c", "d" ,
   2, set<string>"a", "c" ,
   3, set<string>"c", "d" ,
   4, set<string>"a", "c" ,
;

map<string, set<int>> map2;

for (const auto& [id, str_set] : map1) 
  for (const auto& s : str_set) 
    if (map2.count(s) == 0) 
      map2[s] = std::set<int>id;
     else 
      map2[s].emplace(id);
    
  

看起来效率不高。那么有没有其他方法可以加快速度呢? 或者是否有任何适当的数据结构/算法来处理我想要的这些数据?

【问题讨论】:

Looks like it's not efficient 为什么? @ShridharRKulkarni 我只是不喜欢嵌套 除此之外:你不需要ifmap2[s].emplace(id); 在这两种情况下都是正确的 Is your question answered? 【参考方案1】: 使用无序映射和无序集。平均案例常数时间搜索。 您可以用空间换取更快的速度。创建一个布尔矩阵键与值。 O(1) 搜索。

【讨论】:

【参考方案2】:

如果您确实需要“更快”,并且您可以对输入做出一些假设,即 1) 键都是数字并且只是从 1 开始计数,并且 2) 您只有单个字母作为值,那么您可以将整个(小写)字母表放入 int 的位中,您可以使用向量。

但如果这太过分了,我同意之前的回答,哈希表比地图更好(所以使用 unordered_* 版本的地图和集合)。比集合更好的是向量(在这种情况下)。您可以使用 char 向量作为集合,以字母作为索引,并设置 1 表示“存在”。这就像上面存储在一个 int 中的 bitset 版本,但是在一个真实的容器中,这可能更受欢迎。

还有,你的这段代码:

if (map2.count(s) == 0) 
  map2[s] = std::set<int>id;
 else 
  map2[s].emplace(id);

写得更好:

map2[s].emplace(id);

注意:对于地图和集合(以及无序的地图和集合),如果元素不存在,operator[] 将创建该元素,因此您无需进行初始化集合的工作。

【讨论】:

【参考方案3】:

如果您有权访问 Boost 库,则可以使用 boost::bimap 组合您的两个地图。

boost::bimap<boost::bimaps::multiset_of<int>, boost::bimaps::multiset_of<std::string>> map;
map.insert(1, "a");
...
map.insert(4, "c");

然后您可以使用map.left 按数字查找,使用map.right 按字符串查找

【讨论】:

【参考方案4】:

如果您确实需要“更快”,并且您可以对输入做出一些假设,即 1) 键都是数字并且只是从 1 开始计数,并且 2) 您只有单个字母作为值,那么您可以将整个(小写)字母表放入 int 的位中,并将其用作一个集合。使用此类整数的向量,您可以通过扫描向量并测试位来构建输出,如果存在,则将其添加到输出位集中。没有散​​列,没有分配,没有树平衡,几乎零页面错误,预取器友好,直接 O(1),占用空间最小,除了应该在缓存中的向量存储之外几乎没有间接性。

但如果这太过分了,您至少应该考虑使用哈希表而不是映射(所以使用 unordered_map 和 unordered_set)。但比集合更好的是向量(在这种情况下),因为您的键是字母,您可以将向量的大小预先设置为 26,然后从字符中减去“a”并将其用作索引和一个值0 或 1 表示存在。

此外,与上述无关,您的这段代码:

if (map2.count(s) == 0) 
  map2[s] = std::set<int>id;
 else 
  map2[s].emplace(id);

写得更好:

map2[s].emplace(id);

注意:对于地图(和无序地图),如果不存在,operator[] 将创建一个默认构造元素,因此您不需要初始化集合的代码并增加开销。

【讨论】:

以上是关于在其他地图值中查找元素的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中查找用户主目录的最佳方法是啥?

查找所有形式的单词的最佳方法是啥?

在 Rails 中实现“查找商店”功能的最佳方式是啥?

创建 whois 查找的最佳方法是啥? [关闭]

查找阻塞主线程的代码的最佳方法是啥?

在 node.js 中的数组内查找字符串的最佳方法是啥?