【问题标题】:Is there a way to get values using one of the keys in O(1) time有没有办法在 O(1) 时间内使用其中一个键获取值
【发布时间】:2017-07-30 14:46:38
【问题描述】:

我正在为应用程序建模数据,并决定选择字典作为我的数据结构。但是数据中的每一行都有多个键。所以我创建了一个字典,其中包含映射每一行的多个键,例如:

>>> multiKeyDict = {}
>>> multiKeyDict[('key1','key2','key3')] = 'value1'
>>> multiKeyDict.get(('key1','key2','key3'))
'value1'

现在我必须在 O(1) 时间内用key1 检索所有值。根据我的研究,我知道我可以做到:

我也愿意接受任何更好的数据结构,而不是使用字典。

【问题讨论】:

  • 不,没有。
  • 您提到的包将键列表映射到相同的值。如果我正确理解您的问题,您是否想要更多某种层次结构?
  • 为什么不制作两本词典呢? 1 个人喜欢 {'key1':['value1','value2']} 和 1 个人喜欢 {'value1':['key1', 'key2']}
  • 感谢@MartijnPieters。
  • @Chris_Rands 因为值是逗号分隔的长字符串

标签: python dictionary data-modeling


【解决方案1】:

您没有多个密钥。就 Python 字典而言,只有 一个 键,即一个元组对象。除了 O(N) 线性时间之外,您无法搜索元组的组成部分。

如果您的密钥是唯一的,只需单独添加每个密钥:

multiKeyDict['key1'] = multiKeyDict['key2'] = multiKeyDict['key3'] = 'value1'

现在您有 3 个键都引用一个值。值对象在这里没有重复,只有对它的引用。

您找到的multi_key_dict 包使用中间映射将给定的组成键映射到组合键,然后再映射到值。这也为您提供了 O(1) 搜索,同样的限制是每个组成键必须是唯一的。

如果您的键是不是唯一的,那么您需要将每个键映射到另一个容器,然后保存值,例如一个集合:

for key in ('key1', 'key2', 'key3):
    multiKeyDict.setdefault(key, set()).add(value)

现在查找一个键会为您提供该键引用的所有值的集合。

如果您还需要能够组合键,那么您可以使用这些组合添加其他引用。键值对相对便宜,都只是参考。键和值对象本身不重复。

【讨论】:

  • key1 可能有多个值,我不想将值映射到每个键,因为它不会随数据缩放
  • @PseudoAj:那么您没有适合哈希表的数据,并且被困在对该数据结构的线性搜索中。这同样适用于您找到的 multi_key_dict 包。
  • @PseudoAj “不会随数据扩展”是什么意思
  • @PseudoAj:如果有多个值,那么在搜索key1 时,您期望找到什么?如果每个键有 K 个值,则不能进行 O(1) 搜索。
  • @PseudoAj:如果您有数百万条具有复杂关系的记录,那么听起来您需要一个关系数据库。让担心高效的数据结构。
【解决方案2】:

另一种可能性是为共享关键组件的行对象列表建立索引。如果共享任何特定键值的行数很少,这将非常有效。 (假设行对象具有以row.key1row.key2 等形式访问的键,这不是一个非常相关的细节)。未经测试的代码:

index = {}
for row in rows:
    index.setdefault( row.key1, []).append(row)
    index.setdefault( row.key2, []).append(row)
    index.setdefault( row.key3, []).append(row)

然后查找匹配的行,例如 key2key3

candidates = index[ key2] 
if len( index[key3]) < len(candidates): 
    candidates = index[key3] # use key3 if it offers a better distribution
results = []
for cand in candidates:
    if cand.key2 == key2 and cand.key3 == key3: # full test is necessary!
        results.append( cand)

【讨论】:

    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多