大规模双射映射的最佳实现

这是一个有趣的问题:给定大量文本数据(约5 GB的单词作为字符串),我需要构建一个映射,使每个单词都与一个唯一的整数相关联。应该注意的是,它需要以另一种方式工作-每个整数还应该与一个唯一的单词相关联(因此,为什么它是双射映射)。

我还需要能够通过单词的相关编号快速查找单词。

以下是我能想到的最幼稚的实现:

   data_structure = []
   for word in giant_list_of_words:
      if (word not in data_structure):
         data_structure.append(word)
   return data_structure

   def lookup(data_structure,i):
       return data_structure[i]

使用这种方法,映射只是将单词映射到列表中的索引。构建映射很慢,但是查找很快。

这是另一种方法:

def mapping():
   data_structure = {}
   count = 0
   for word in giant_list_of_words:
      if (word not in data_structure):
         data_structure[word] = count
         count += 1
   return data_structure

def lookup(data_structure,i):
   retval = ''
   for key in data_structure:
      if (data_structure[key] == i):
          retval = key
          break
   return retval

构建速度很快,但索引编制却很慢。有什么想法吗?

hliyouheng 回答:大规模双射映射的最佳实现

我认为很少有绝对最佳的方法来解决Python中的数据结构设计问题,但是对于这个问题,有一个不错的选择。

Python中的每个对象(包括字符串)都有一个唯一的数字id(obj),并且在该对象的生命周期内始终不变。

碰巧_ctypes模块有一个名为PyObj_FromPtr的函数,该函数通过其id查找对象:

>>> word = 'supercalifragilisticexpialadocious'
>>> word_id = id(word)
>>> word_id
139817888649440
>>> from _ctypes import PyObj_FromPtr
>>> PyObj_FromPtr(word_id)
'supercalifragilisticexpialadocious'

这一切都是语言内置的-不管您是否需要,Python都会将这些ID分配给您的对象,并且查找速度很快,因为(作为CPython实现的详细信息)对象的ID是其内存地址。因此很难想象有任何更有效的解决方案。

,

选项(1)

如果您的字符串具有以下属性:

  • 字符串不区分大小写。 "ApPle" == "APPLE" == "apple"
  • 仅使用字符0-9a-z
  • '/\:;,.!@#$%^&*(){}[]+-"

然后,您可以使用基数36表示法将字符串转换为整数。

hash_val = int("apple",base=36)

选项(2)

请注意,python字符串具有内置的hash函数:

words = [
    "apple","banana","apple"
    "apple","kiwi","honeydew",]
d = dict()
d_inv = dict()
for word in words:
    hval = hash(word)
    d[word] = hash(word)
    d_inv[hval] = word

print(
    "\n".join(
        str(key).ljust(20) + str(val) for key,val in d.items()
    )
)

但是,哈希值仅在程序运行时保持恒定。每次关闭程序时,它都会更改。您将不得不将它们保存到文件或其他内容中。在一次运行中,hash("apple")1406220762,在下一次运行中是1187353108

本文链接:https://www.f2er.com/3148227.html

大家都在问