Python + Sqlite 的字符串相似度(Levenshtein 距离/编辑距离)

2024-03-03

Python+Sqlite 中是否有可用的字符串相似性度量,例如使用sqlite3模块?

用例示例:

import sqlite3
conn = sqlite3.connect(':memory:')
c = conn.cursor()
c.execute('CREATE TABLE mytable (id integer, description text)')
c.execute('INSERT INTO mytable VALUES (1, "hello world, guys")')
c.execute('INSERT INTO mytable VALUES (2, "hello there everybody")')

此查询应匹配 ID 为 1 的行,但不匹配 ID 为 2 的行:

c.execute('SELECT * FROM mytable WHERE dist(description, "He lo wrold gyus") < 6')

如何在 Sqlite+Python 中做到这一点?

关于我迄今为止发现的内容的注释:

  • The 编辑距离 https://en.wikipedia.org/wiki/Levenshtein_distance,即将一个单词更改为另一个单词所需的最小单字符编辑(插入、删除或替换)次数可能很有用,但我不确定 Sqlite 中是否存在官方实现(我见过一些自定义实现,例如this one https://github.com/mateusza/SQLite-Levenshtein)

  • The 达默劳-莱文施泰因 https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance是相同的,只是它也允许在 2 个相邻字符之间换位;它也被称为编辑距离 https://en.wikipedia.org/wiki/Edit_distance

  • 我知道有可能定义一个函数 https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.create_function我自己,但实现这样的距离将是不平凡的(对数据库进行超高效的自然语言处理比较确实是不平凡的),这就是为什么我想看看Python / Sqlite是否已经具有这样的工具

  • Sqlite 具有 FTS(全文搜索)功能:FTS3 https://www.sqlite.org/fts3.html, FTS4 https://www.sqlite.org/fts3.html#differences_between_fts3_and_fts4, FTS5 https://sqlite.org/fts5.html

    CREATE VIRTUAL TABLE enrondata1 USING fts3(content TEXT);     /* FTS3 table */
    CREATE TABLE enrondata2(content TEXT);                        /* Ordinary table */
    SELECT count(*) FROM enrondata1 WHERE content MATCH 'linux';  /* 0.03 seconds */
    SELECT count(*) FROM enrondata2 WHERE content LIKE '%linux%'; /* 22.5 seconds */
    

    但我没有找到关于字符串比较与这样的“相似距离”,FTS的功能MATCH or NEAR似乎没有字母变化等相似性衡量标准。

  • 而且这个答案 https://stackoverflow.com/a/35025747/1422096表明:

    SQLite 的 FTS 引擎基于标记 - 搜索引擎尝试匹配的关键字。
    有多种标记器可用,但它们相对简单。 “简单”分词器只是将每个单词分开并将其小写:例如,在字符串“The Quick Brown Fox Jumps Over the Lazy Dog”中,单词“Jumps”会匹配,但不会匹配“Jump”。 “porter”分词器更先进一些,它去掉了单词的词形变化,这样“jumps”和“jumping”就会匹配,但像“jmups”这样的拼写错误则不会。

    遗憾的是,后者(“jmups”无法找到与“jumps”类似的事实)使其对于我的用例来说不切实际。


这是一个随时可用的示例test.py:

import sqlite3
db = sqlite3.connect(':memory:')
db.enable_load_extension(True)
db.load_extension('./spellfix')                 # for Linux
#db.load_extension('./spellfix.dll')            # <-- UNCOMMENT HERE FOR WINDOWS
db.enable_load_extension(False)
c = db.cursor()
c.execute('CREATE TABLE mytable (id integer, description text)')
c.execute('INSERT INTO mytable VALUES (1, "hello world, guys")')
c.execute('INSERT INTO mytable VALUES (2, "hello there everybody")')
c.execute('SELECT * FROM mytable WHERE editdist3(description, "hel o wrold guy") < 600')
print c.fetchall()
# Output: [(1, u'hello world, guys')]

重要提示:距离编辑距离3 https://sqlite.org/spellfix1.html被标准化,以便

值100用于插入和删除,150用于替换


以下是在 Windows 上首先要做的事情:

  1. 下载https://sqlite.org/2016/sqlite-src-3110100.zip https://sqlite.org/2016/sqlite-src-3110100.zip, https://sqlite.org/2016/sqlite-amalgamation-3110100.zip https://sqlite.org/2016/sqlite-amalgamation-3110100.zip并解压它们

  2. Replace C:\Python27\DLLs\sqlite3.dll由新的sqlite3.dll https://www.sqlite.org/download.html from here https://www.sqlite.org/download.html。如果跳过这个,你会得到一个sqlite3.OperationalError: The specified procedure could not be found later

  3. Run:

    call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"  
    

    or

    call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x64
    cl /I sqlite-amalgamation-3110100/ sqlite-src-3110100/ext/misc/spellfix.c /link /DLL /OUT:spellfix.dll
    python test.py
    

    (对于 MinGW,它将是:gcc -g -shared spellfix.c -I ~/sqlite-amalgation-3230100/ -o spellfix.dll)

以下是在 Linux Debian 上执行此操作的方法:

(基于这个答案 https://stackoverflow.com/a/36427821/1422096)

apt-get -y install unzip build-essential libsqlite3-dev
wget https://sqlite.org/2016/sqlite-src-3110100.zip
unzip sqlite-src-3110100.zip
gcc -shared -fPIC -Wall -Isqlite-src-3110100 sqlite-src-3110100/ext/misc/spellfix.c -o spellfix.so
python test.py

以下是在使用较旧 Python 版本的 Linux Debian 上执行此操作的方法:

如果您的发行版的 Python 有点旧,则需要另一种方法。作为sqlite3模块是Python内置的,看起来不简单 https://github.com/ghaering/pysqlite/issues/123#issuecomment-381447917升级它(pip install --upgrade pysqlite只会升级 pysqlite 模块,而不是底层 SQLite 库)。因此这个方法 https://stackoverflow.com/a/49847451/1422096例如,如果import sqlite3; print sqlite3.sqlite_version是3.8.2:

wget https://www.sqlite.org/src/tarball/27392118/SQLite-27392118.tar.gz
tar xvfz SQLite-27392118.tar.gz
cd SQLite-27392118 ; sh configure ; make sqlite3.c ; cd ..
gcc -g -fPIC -shared SQLite-27392118/ext/misc/spellfix.c -I SQLite-27392118/src/ -o spellfix.so
python test.py   # [(1, u'hello world, guys')]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python + Sqlite 的字符串相似度(Levenshtein 距离/编辑距离) 的相关文章

  • 围绕 readline 构建的 python 批处理的触发器选项卡完成

    背景 我有一个 python 程序 它导入并使用 readline 模块来构建自制的命令行界面 我有第二个 python 程序 围绕 Bottle 一个 Web 微框架构建 充当该 CLI 的前端 第二个 python 程序向第一个程序打开
  • 从数据框中按索引删除行

    我有一个数组wrong indexes train其中包含我想从数据框中删除的索引列表 0 63 151 469 1008 要删除这些索引 我正在尝试这样做 df train drop wrong indexes train 但是 代码失败
  • Python Popen 与 psexec 挂起 - 不良结果

    我对 subprocess Popen 和我认为是管道的问题有疑问 我有以下代码块 从 cli 运行时 100 都不会出现问题 p subprocess Popen psexec serverName get cmd c ver echo
  • django_openid_auth TypeError openid.yadis.manager.YadisServiceManager 对象不是 JSON 可序列化

    I used django openid auth在我的项目上 一段时间以来它运行得很好 但今天 我测试了该应用程序并遇到了这个异常 Environment Request Method GET Request URL http local
  • 使用 python 进行串行数据记录

    Intro 我需要编写一个小程序来实时读取串行数据并将其写入文本文件 我在读取数据方面取得了一些进展 但尚未成功地将这些信息存储在新文件中 这是我的代码 from future import print function import se
  • 我怎样才能更多地了解Python的内部原理? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我使用Python编程已经有半年多了 我对Python内部更感兴趣 而不是使用Python开发应用程序
  • python 模拟第三方模块

    我正在尝试测试一些处理推文的类 我使用 Sixohsix twitter 来处理 Twitter API 我有一个类充当 Twitter 类的外观 我的想法是模拟实际的 Sixohsix 类 通过随机生成新推文或从数据库检索它们来模拟推文的
  • Python逻辑运算符优先级[重复]

    这个问题在这里已经有答案了 哪个运算符优先4 gt 5 or 3 lt 4 and 9 gt 8 这会被评估为真还是假 我知道该声明3 gt 4 or 2 lt 3 and 9 gt 10 显然应该评估为 false 但我不太确定 pyth
  • 如何计算numpy数组中元素的频率?

    我有一个 3 D numpy 数组 其中包含重复的元素 counterTraj shape 13530 1 1 例如 counterTraj 包含这样的元素 我只显示了几个元素 array 136 129 130 103 102 101 我
  • 首先对列表中最长的项目进行排序

    我正在使用 lambda 来修改排序的行为 sorted list key lambda item item lower len item 对包含元素的列表进行排序A1 A2 A3 A B1 B2 B3 B 结果是A A1 A2 A3 B
  • 将 2D NumPy 数组按元素相乘并求和

    我想知道是否有一种更快的方法 专用 NumPy 函数来执行 2D NumPy 数组的元素乘法 然后对所有元素求和 我目前使用np sum np multiply A B 其中 A B 是相同维度的 NumPy 数组m x n 您可以使用np
  • 使用 NumPy 将非均匀数据从文件读取到数组中

    假设我有一个如下所示的文本文件 33 346 1223 10 23 11 23 12 23 13 23 14 23 15 23 16 24 10 24 11 24 12 24 13 24 14 24 15 24 16 25 14 25 15
  • 使用yield 进行字典理解

    作为一个人为的例子 myset set a b c d mydict item yield join item s for item in myset and list mydict gives as cs bs ds a None b N
  • 使用 PyTorch 分布式 NCCL 连接失败

    我正在尝试使用 torch distributed 将 PyTorch 张量从一台机器发送到另一台机器 dist init process group 函数正常工作 但是 dist broadcast 函数中出现连接失败 这是我在节点 0
  • Tkinter - 浮动窗口 - 调整大小

    灵感来自this https stackoverflow com a 22424245 13629335问题 我想为我的根窗口编写自己的调整大小函数 但我刚刚注意到我的代码显示了一些性能问题 如果你快速调整它的大小 你会发现窗口没有像我希望
  • Ubuntu 上的 Python 2.7

    我是 Python 新手 正在 Linux 机器 Ubuntu 10 10 上工作 它正在运行 python 2 6 但我想运行 2 7 因为它有我想使用的功能 有人敦促我不要安装 2 7 并将其设置为我的默认 python 我的问题是 如
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • 检查字典键是否有空值

    我有以下字典 dict1 city name yass region zipcode phone address tehsil planet mars 我正在尝试创建一个基于 dict1 的新字典 但是 它不会包含带有空字符串的键 它不会包
  • Python 无法使用套接字绑定我的外部/公共 IP 地址,给出错误但是当使用本地 IP 地址时,错误不会显示

    这是出现主要错误的代码 与我的本地 IP 的绑定将起作用 s bind 192 168 1 4 port 与我的公共 IP 的绑定失败并出现以下错误 s bind 99 99 99 99 port WinError 10049 请求的地址在
  • 列表值的意外更改

    这是我的课 class variable object def init self name name alias parents values table name of the variable self name 这是有问题的函数 f

随机推荐