Python字典很慢(2-D哈希表)

时间:2012-12-24 15:01:10

标签: python dictionary hashtable

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

在Python中,我尝试过:

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

但事实证明非常慢

那么如何在Python中有效地实现二维哈希表?

更新

我的程序很重要。由于Python dict动态分配内存,我可以看到程序在运行时等待内存分配,而CPU使用率有时很低,有时很高。

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

4 个答案:

答案 0 :(得分:2)

如果您的代码没有问题取决于您的用例。如果你想要hash[1][2]这样的东西,即你可以迭代hash[x]而不触及其他hash[y]元素,那么元组密钥不是是一个很好的解决方案。在这种情况下,你最好这样做:

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

这使得hash dict包含具有复合(元组)键的单个dict的其他dicts instad。使用defaultdict主要是糖,以避免hash.setdefault(1, {})调用创建subdicts,以防它们不存在。

答案 1 :(得分:1)

你用复合键做了1级dict:

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

另一种选择是2级词典:

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

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

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

答案 2 :(得分:0)

如果您遵循以下代码,您可以执行与C类似的操作:

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

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

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

等,等...

答案 3 :(得分:0)

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

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