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中执行此操作?
关于到目前为止我发现的内容的注释:
Levenshtein distance,即将一个单词更改为另一个单词所需的最小单字符编辑数(插入,删除或替换)可能很有用,但我不确定是否Sqlite中存在官方实现(我见过一些自定义实现,如this one)
Damerau-Levenshtein是相同的,除了它还允许在2个相邻字符之间进行转置;它也被称为Edit distance
我知道自己可以define a function,但实现这样的距离将是非常重要的(对数据库进行超级高效的自然语言处理比较实际上并非无关紧要),这就是我想要的原因看看Python / Sqlite是否已经具备了这样的工具
Sqlite具有FTS(全文搜索)功能:FTS3,FTS4,FTS5
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
或NEAR
似乎没有字母变化等的相似性度量。
此外this answer显示:
SQLite的FTS引擎基于令牌 - 搜索引擎试图匹配的关键词 有各种各样的标记器,但它们相对简单。 “简单”的标记器简单地将每个单词拆分并对其进行小写:例如,在字符串“快速的棕色狐狸跳过懒狗”中,单词“jumps”会匹配,但不会“跳”。 “porter”标记器有点高级,剥离了单词的结合,因此“跳跃”和“跳跃”匹配,但是像“jmups”这样的拼写错误不会。
后者(“jmups”无法与“跳跃”类似的事实)使得我的用例难以实现,遗憾的是。
答案 0 :(得分:3)
以下是一个现成的示例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')]
重要提示:距离editdist3已标准化,以便
值100用于插入和删除,150用于替换
下载https://sqlite.org/2016/sqlite-src-3110100.zip,https://sqlite.org/2016/sqlite-amalgamation-3110100.zip并解压缩
将C:\Python27\DLLs\sqlite3.dll
替换为sqlite3.dll的新here。如果跳过此内容,您将获得sqlite3.OperationalError: The specified procedure could not be found
以后的
执行命令
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
或
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
)
(基于this answer)
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有点旧,则需要另一种方法。由于sqlite3
模块是内置于Python的,因此升级它似乎not straightforward(pip install --upgrade pysqlite
只会升级pysqlite模块,而不是升级基础SQLite库)。因此this method例如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')]
答案 1 :(得分:1)
我实现了与距离相关的函数(Damerau-Levenshtein、Jaro-Winkler、最长公共子串和子序列)作为 SQLite 运行时可加载扩展。支持任何 UTF-8 字符串。