【问题标题】:Python dictionary very slow(2-D hash table)Python 字典很慢(二维哈希表)
【发布时间】:2012-12-24 15:01:10
【问题描述】:

我想使用二维数组作为哈希表,在 C 语言中,就像:
hash[1][2] = 1

在 Python 中,我尝试过:

hash = {}
hash[1,2] = 1

但事实证明它非常慢

那么如何在 Python 中高效地实现一个二维哈希表呢?​​

更新:

我的程序是一个计算量很大的程序。由于 Python dict 动态分配内存,我可以看到程序在运行时一直在等待内存分配,而 CPU 使用率时而低时而高。

C 风格的二维数组应该没问题,但我不知道如何在 Python 中实现它。

【问题讨论】:

  • 定义“非常慢”。只要您不需要迭代其中的一部分,元组就是一个非常好的键。
  • Python 的 dicts 是 Python 中最快的哈希表,因为它们是用 C 实现的。提供 很多 更多关于您的代码和性能问题的详细信息。
  • @ThiefMaster “非常慢”意味着当我运行程序时(计算量大的程序),CPU 使用率很低,我可以看到程序正在等待内存分配。元组支持类似:t = ();t[1,2]=1?
  • can.:用更多细节更新问题:您创建了多少个键,值真的只是整数还是其他?你使用什么样的算法?读和写的混合是什么?为什么不只使用二维数组?稀疏吗?所有这些细节都将有助于获得正确的答案。
  • @NedBatchelder 一个 C 风格的 2D 数组应该没问题,我只是不知道如何在 Python 中实现它

标签: python dictionary hashtable


【解决方案1】:

您的代码是否正常取决于您的用例。如果你想要hash[1][2] 之类的东西,也就是说,你可以在不触及其他hash[y] 元素的情况下迭代hash[x],那么元组键不是一个好的解决方案。在这种情况下,您最好这样做:

from collections import defaultdict
hash = defaultdict(dict)
hash[1][2] = 1

这使hash 成为一个包含其他字典的字典,而不是具有复合(元组)键的单个字典。使用defaultdict 主要是为了避免hash.setdefault(1, {}) 调用创建子字典,以防它们尚不存在。

【讨论】:

  • 还请注意,每次调用has.setdefault(1,{}) 都会在第二个参数中创建空字典,因为它很有可能需要 - defaultdict 不需要这样做,因为它是创建的使用工厂函数,因此只有在需要初始化新键的条目时才会创建新元素。
【解决方案2】:

你用复合键做了 1 级 dict:

arr = { (1,2): "a", (1,3): "b" }

另一种选择是 2 级字典:

arr = { 1: { 2: "a", 3: "b" }}

还有一个是使用例如numpy.array(), IIRC 它不能是稀疏的。

scipy 有稀疏的 marix 类,很有用。

【讨论】:

    【解决方案3】:

    如果你按照下面的代码,你可以做一些类似于 C 的事情:

    a={}
    a[1]={}
    a[2]={}
    

    现在,'a' 是一个字典字典,用于模拟您的用例。 现在您可以将其用作:

    a[1][1] = anyVal;
    a[1][2] = otherVal;
    a[2][1] = anotherVal; 
    

    等等等等……

    【讨论】:

      【解决方案4】:

      如果可能的键集很小,您还可以使用列表列表。这是一个非常简单的马尔可夫生成器,它使用输入语料库中的字符对来创建新的“句子”。注意 list-of-lists markov_pairs 的初始化,这是使用 Python 列表获取二维数组的方式。

      import random
      import string
      all_letters = string.ascii_uppercase + string.ascii_lowercase
      
      corpus = """Lorem ipsum dolor sit amet, consectetur 
                  adipisicing elit, sed do eiusmod tempor incididunt ut 
                  labore et dolore magna aliqua. Ut enim ad minim veniam, 
                  quis nostrud exercitation ullamco laboris nisi ut 
                  aliquip ex ea commodo consequat. Duis aute irure dolor 
                  in reprehenderit in voluptate velit esse cillum dolore 
                  eu fugiat nulla pariatur. Excepteur sint occaecat 
                  cupidatat non proident, sunt in culpa qui officia 
                  deserunt mollit anim id est laborum."""
      # normalize all spaces to single spaces
      corpus = ' '.join(corpus.split())
      
      # initialize 2-D array for sequence tally
      markov_pairs = [[0]*256 for i in range(256)]
      
      # make sure every letter and space has at least *some* probability of following
      # any other letter
      for sublist in markov_pairs:
          for i in range(len(sublist)):
              if chr(i) in all_letters+' ':
                  sublist[i] += 1
      
      # pairwise iterate over input corpus, updating markov pairs with observed pairs
      it = iter(corpus)
      last = next(it)
      for c in it:
          markov_pairs[ord(last)][ord(c)] += 10000
          last = c
      
      # function to guess a next character, given a starting character, based on the
      # frequencies found in the input corpus
      def getNext(pairs, from_):
          probs = pairs[ord(from_)]
          num = random.randint(0,sum(probs))
          # reorder probs so highest weights are up front
          for p,c in sorted(((p,chr(i)) for i,p in enumerate(probs) if p),reverse=True):
              num -= p
              if num <= 0: break
          return c
      
      # generate some new text based on the corpus
      for i in range(20):
          ret = []
          last = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
          while last in (all_letters+' '):
              ret.append(last)
              last = getNext(markov_pairs, last)
          print ''.join(ret)
      

      版画(有点像拉丁和图雷特综合症的混合体):

      NEx quite eria nalorunorein ulag Utalidor eniqum atet
      SPllalalad nsiqudont intret
      RCve ollat rim don epored lonidolid im cuatempt esepiaent furiutautr lit m vehenise vex nst
      Wveta cet at mp icur e co anorepit pidomodor ng ala
      Lorurim
      Fm dorisseiuimondedor nid lunor
      HJcupter Excarcuro don itaboffuitese cosensest emm cim e ct vonut s cosudodisir
      Habocinim issit nia iat uininolla iatere e a aulict catenipa pont
      Sgiteps a t cor
      PRRfinsmabommo dupagnit norer olulaboi mipit
      Exearicat ites e ngn ptrequmpa n uiuia imema cuause dont
      Ex inod in amost met
      Ae s cutes ia
      CKx fint m e cor olllulalicun sedoreuipa ciuam
      Oorolatrenor cum a is d Dum e edocipit m cimont eum lliofinsit aret am elorellisterexereminidit elolititresuntexelimomp poisudinisenorute a abolor ex ont
      BZt ret taenorenat miqururcon Duit sea ca vexexeserurisulollat
      Tlit aboceda qupriut m cualllupip cad d s dect
      Ohet em uidid iam it d edollat a ssicaruir idor d unon n e e colaum funsiabontiataboressusia ffise Dum vororeruisedor redeit aupos cat epom ipt
      GDust
      Hyalorunofit d qur enser
      

      【讨论】: