- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一本包含约 150,000 个键的字典。没有重复的键。每个 key 的长度为 127 个字符,每个 key 在 1-11 个位置上有所不同(大多数差异发生在 key 的末尾)。每个键的值是一个唯一的 ID 和一个空白列表 []。对于一个给定的键,我想找到所有其他恰好相差 1 个字符的键,然后将 ID 附加到给定的键空白列表中。最后我想要一个键和它的值(一个 ID 和一个包含一个字符不同的所有键的列表)。
我的代码可以工作,但问题是它太慢了。双 for 循环是 150,000^2 = ~250 亿。在我的电脑上,我每分钟可以执行约 200 万次循环(每次都执行 match1 函数)。这将需要大约 8 天的时间才能完成。没有 match1 函数的循环运行速度快约 7 倍,因此将在约 1 天内完成。
我想知道是否有人知道如何提高速度?
# example dictionary
dict = {'key1' : ['1', []], 'key2' : ['2', []], ... , 'key150000' : ['150000', []]}
def match1(s1,s2,dict):
s = 0
for c1, c2 in zip(reversed(s1), reversed(s2)):
if s < 2:
if c1 != c2:
s = s + 1
else:
break
if s == 1:
dict1[s1][1].append(dict1[s2][0])
for s1 in dict:
for s2 in dict:
match1(s1,s2,dict)
最佳答案
目前您正在检查每个键与其他每个键的总 O(n^2)
比较。洞察力是我们只需要检查其他 key 的一小部分。
假设每个键的字符具有 k
不同值的字母表。例如,如果您的 key 是由 a-z
和 0-9
组成的简单 ASCII 字符串,则为 k = 26 + 10 = 30
。
给定任何键,我们可以生成所有可能的键,这些键距离一个字符:有 127 * k
这样的字符串。在您将每个键与大约 150,000 个其他键进行比较之前,现在我们只需要与 127 * k
进行比较,在 k = 30
的情况下为 3810。这将整体时间复杂度从 O(n^2)
降低到 O(n * k)
,其中 k
是一个独立于 n
的常量。 这是当您扩展 n
时真正加速的地方。
这里有一些代码可以生成一个键的所有可能的邻居:
def generate_neighbors(key, alphabet):
for i in range(len(key)):
left, right = key[:i], key[i+1:]
for char in alphabet:
if char != key[i]:
yield left + char + right
所以,例如:
>>> set(generate_neighbors('ab', {'a', 'b', 'c', 'd'}))
{'aa', 'ac', 'ad', 'bb', 'cb', 'db'}
现在我们计算每个键的邻域:
def compute_neighborhoods(data, alphabet):
keyset = set(data.keys())
for key in data:
possible_neighbors = set(generate_neighbors(key, alphabet))
neighbors = possible_neighbors & keyset
identifier = data[key][0]
for neighbor in neighbors:
data[neighbor][1].append(identifier)
现在举个例子。假设
data = {
'0a': [4, []],
'1f': [9, []],
'27': [3, []],
'32': [8, []],
'3f': [6, []],
'47': [1, []],
'7c': [2, []],
'a1': [0, []],
'c8': [7, []],
'e2': [5, []]
}
然后:
>>> alphabet = set('abcdef01234567890')
>>> compute_neighborhoods(data, alphabet)
>>> data
{'0a': [4, []],
'1f': [9, [6]],
'27': [3, [1]],
'32': [8, [5, 6]],
'3f': [6, [8, 9]],
'47': [1, [3]],
'7c': [2, []],
'a1': [0, []],
'c8': [7, []],
'e2': [5, [8]]}
还有一些优化我没有在这里实现。首先,你说这些键在后面的字符上大多不同,而且它们最多在 11 个位置不同。这意味着我们可以更聪明地计算交集 possible_neighbors & keyset
和生成邻域。首先,我们修改 generate_neighbors
以首先修改 key 的 trailing 字符。然后,我们不是一次生成整个邻居集,而是一次生成一个,并检查是否包含在 data
字典中。我们跟踪找到了多少个,如果找到 11 个,我们就会中断。
我没有在我的回答中实现这个的原因是我不确定它是否会导致显着的加速,并且实际上可能更慢,因为这意味着删除优化的 Python带有纯 Python 循环的内置(设置交集)。
关于python - for loop in for loop 的更快替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34114554/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!