2013-08-05 19 views
11

Bir diksiyonun belirli bir dizeyle başlayan bir anahtar içerip içermediğini belirlemenin en hızlı yolu nedir? Doğrusaldan daha iyisini yapabilir miyiz? Sadece bir anahtarın başlangıcını bildiğimizde O (1) işlemine nasıl ulaşabiliriz?python dict kısmi anahtar kelimesiyle arama yapmanın en hızlı yolu

for key in dict.keys(): 
    if key.start_with(str): 
     return True 
return False 
+0

: (: "h" burada) Ve tabii ki, kısa önekleri için zihni olası birçok çarpışmalarda var. Ayrıca bu iki anahtar aynı önekle başlıyorsa, bu durum odalara belirsizlikler bırakıyor. – Hyperboreus

+0

Bunu yapabilen veri yapıları vardır, ancak Python standart kitaplığında bulunmazlar. Örneğin, deneme veya ikili arama ağaçları. – delnan

+3

Soru, hız ile ilgili olduğundan, 'dict_:' anahtarında 'dict_.keys(): 'anahtarından çok daha hızlı olduğunu belirtmek zorundayım. –

cevap

24

dicti ön işlenmesi olmadan, O(n) Yapabileceğiniz en iyisi:

İşte şimdiki çözümdür. Yine de karmaşık olmak zorunda değildir:

any(key.startswith(mystr) for key in mydict) 

(. O zaten iki built-in functions isimleri dict ve değişken adı olarak str kullanmayın)

Eğer can preprocess Eğer Dict, anahtarları bir önek ağacına koymayı düşünün (aka trie). Wikipedia makalesinde Python implementation bile var. Anahtar foo için size f, fo ve foo eklemek diye

+0

Bir tray O (log N), O değil (1). Ama neredeyse burada istediğin şey kesinlikle. Bu veri yapısı için paradigma durumudur. – abarnert

+0

@abarnert Hayır, en büyük dize uzunluğunun dizgilerdeki logaritmik olduğuna dair garip bir varsayım yapmazsanız, hayır. Bir trie'de arama, anahtarın uzunluğunda doğrusaldır ve dolayısıyla trie'deki dizelerin sayısından bağımsızdır. – delnan

+0

@delnan: N dizelerin sayısı değil, farklı sembollerin sayısı. Küçük ve statik sayıda sembolünüz varsa (örn. ASCII dizeleriyle), bunu göz ardı edebilirsiniz. Çok sayıda sembolünüz varsa (örn., Keyfi Unicode), yapamazsınız. Ya her bir trie seviyesinde lineer bir arama yapıyorsunuz ya da bir kere N log. (Evet, dizinin uzunluğunda _also_ doğrusal ve bunu ihmal ettim…) – abarnert

0

Sen, dict sokulan anahtarların tüm önekleri koyabiliriz. (Ben giderdim günlük kullanım için

def insert_with_prefixes(key, value, dict_): 
    prefixes = (key[:i+1] for i in xrange(len(key))) 
    dict_.update((prefix, value) for prefix in prefixes) 

: Sen O (1) araması olurdu, ancak (k anahtar uzunluğu O (k)) ön işleme üzerinde zaman harcamak ve büyük miktarda bellek kaybına neden olacak şekilde ve ben arshajii's cevabındaki yöntemle giderim. Sana anahtarın bir parçası anahtarın karma tahmin edemediği gibi daha iyi bir şey modernleşmek şüpheliyim

>>> a = {} 
>>> insert_with_prefixes('hello', 'world', a) 
>>> insert_with_prefixes('homo', 'sapiens', a) 
>>> a 
{'h': 'sapiens', 'hom': 'sapiens', 'homo': 'sapiens', 'ho': 'sapiens', 
'hel': 'world', 'hell': 'world', 'hello': 'world', 'he': 'world'} 
İlgili konular