可以使用python字典理解来创建子字符串及其位置的字典吗?

use*_*699 6 python dictionary dictionary-comprehension

给定一串字符,我想创建一个包含在字符串中的所有n字符子串的字典,其中字典键是子字符串,值是列表.列表的第一个元素是子字符串的出现次数,列表的第二个元素是这些出现的起始位置列表.

例如,使用n=3,字符串'abcdabcxdabc'会生成此字典:

{'abc': [3, [0, 4, 9]], 
 'cda': [1, [2]], 
 'dab': [2, [3, 8]], 
 'bcd': [1, [1]], 
 'cxd': [1, [6]], 
 'bcx': [1, [5]], 
 'xda': [1, [7]]}
Run Code Online (Sandbox Code Playgroud)

下面的代码工作并且是有效的,因为它只遍历字符串一次,但我想知道是否有更优雅和/或更pythonic方式来执行此操作,可能使用字典理解.我对python很新,并且仍在试图弄清楚何时使用理解等有意义(甚至可能).

text = 'abcdabcxdabc'
n = 3
d = {}
for i in range(len(text) - n + 1):
    sub = text[i:i + n]
    if sub in d:
        d[sub][0] += 1
        d[sub][1].append(i)
    else:
        d[sub] = [1, [i]]
print(d)    
Run Code Online (Sandbox Code Playgroud)

更新:感谢所有回复.他们通常证实我怀疑这太复杂了,无法在一次理解中有效地实施(但感谢火山表明如果效率不是一个问题就有可能实现).感谢RemcoGerlich和Ignacio Vazquez-Abrams将我指向defaultdict.我将不得不深入研究这一点.我的计时结果表明,与dict相比,初始化defaultdict会有更多的开销,但是运行时间可能稍微快一点,至少对于这个例子.(时间结果发布在下面单独的评论中.)现在我想知道是否有任何情况下dict优先于defaultdict.还有,感谢Narcolei指点我的timeit功能.

Ign*_*ams 4

问题是v[0]取决于 或 的长度v[1],这意味着要生成的操作v[1]必须执行两次,或者必须迭代字典才能填充以v[0]替换第一次包含的虚拟值。

另一个问题是字典推导式期望整个键和值立即可用,这意味着您必须运行列表推导式才能获取字符的所有索引,这意味着整个操作变为 O(n 2 )

我要做的唯一优化是替换创建,d这样您就不需要检查密钥包含。

d = collections.defaultdict(lambda: [0, []])
Run Code Online (Sandbox Code Playgroud)