【问题标题】:Maps in Go - how to avoid double key lookup?Go 中的地图 - 如何避免双键查找?
【发布时间】:2015-03-16 23:27:56
【问题描述】:

假设我想更新地图中的一些现有值,或者如果找不到键,则执行其他操作。在不执行 2 次查找的情况下,我该怎么做?以下 C++ 代码的 golang 等价物是什么:

auto it = m.find(key);
if (it != m.end()) {
    // update the value, without performing a second lookup
    it->second = calc_new_value(it->second);
} else {
    // do something else
    m.insert(make_pair(key, 42));
}

【问题讨论】:

标签: go


【解决方案1】:

Go 不像 C++ 那样公开映射的内部(键、值)对数据结构,因此您无法完全复制它。

一种可能的解决方法是创建映射指针的值,这样您就可以在映射中保留相同的值,但更新它们指向的内容。例如,如果 mmap[int]*int,您可以使用以下命令更改值:

v := m[10]
*v = 42

话虽如此,如果减少哈希查找次数所节省的成本会被额外的内存管理开销所消耗,我不会感到惊讶。因此,无论您选择何种解决方案,都值得进行基准测试。

【讨论】:

  • 投反对票有什么理由吗?如果您认为有问题,我可以更新答案。
【解决方案2】:

您不能。这种情况实际上是与Python类型的字典一样。然而,它不应该的问题。这两个查询和任务将转至地图摊销O(1)。组合所述两个操作具有相同的时间复杂度。 P>

【讨论】:

  • 以我基准之一我得到这个(地图访问占据了CPU周期):1.58s 28.11% 28.11% 1.66s 29.54% runtime.mapaccess2_fast64 0.87s 15.48% 43.59% 0.92s 16.37% runtime.mapaccess1_fast64 跨度>
  • >查找并分配给进入地图摊销O(1)很抱歉,这是我的宠物忿怒;它的哈希映射的表现的常见和严重的误解。查找是相对于地图的大小恒定 i>的。它是O(n)相对于所述键的大小 i>的(通常散列函数是线性的比特在密钥的数量)。这样,比如说,串密钥,散列可以很容易地支配和转查找为线性运算,和O(2N)与O(N)可以使一个重要的区别。跨度>
  • @ decitrig这是非常有趣的。但是,如果该键都是相同的长度,或长度本身是O(1),我们不关心?此外,如果我们把重点为k的长度,它的O(k)和我们知道k较小。也有许多语言缓存哈希过,巨蟒例如试。 SPAN>
  • 当然,如果我们允许做大约密钥大小或执行任意的假设,我们可以把它作为有效的,因为我们想要的。但问题并没有规定有关密钥大小事情,它不是有关Python。究其原因C ++有API引用笔者正是为了避免昂贵的计算哈希值多次,因为它(如围棋)也没有办法缓存哈希结果任意类型。这类似于快速排序:的qsort不是nlgn,它的nlgn的在平均情况下 i>的。我之所以得到挑剔,这是因为哈希泛洪攻击是一个真实的东西。 SPAN>
猜你喜欢
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
相关资源
最近更新 更多