字符串按相似度排序

字符串按相似度排序

int calcDistance(const QString& source, const QString& target)
{
    int n = source.length();
    int m = target.length();

    if (m == 0) return n;
    if (n == 0) return m;

    QVector <QVector <int>> matrix(n + 1);
    for (int i = 0; i <= n; i++) matrix[i].resize(m + 1);
    for (int i = 1; i <= n; i++) matrix[i][0] = i;
    for (int i = 1; i <= m; i++) matrix[0][i] = i;

    for (int i = 1; i <= n; i++)
    {
        const QChar si = source.at(i - 1);

        for (int j = 1; j <= m; j++)
        {
            const QChar dj = target.at(j - 1);
            int cost;

            if (si == dj)
                cost = 0;
            else
                cost = 1;

            const int above = matrix[i - 1][j] + 1;
            const int left = matrix[i][j - 1] + 1;
            const int diag = matrix[i - 1][j - 1] + cost;
            matrix[i][j] = std::min(above, std::min(left, diag));
        }
    }

    return matrix[n][m];
}

struct YxObjectLessThan {
    QString target;
    YxObjectLessThan(const QString& target_) {
        target = target_;
    }
    bool operator()(const QVariantMap& a, const QVariantMap& b) const {
        QString na = a.value("yxmc", "").toString();
        QString nb = b.value("yxmc", "").toString();
        int da = calcDistance(na, target);
        int db = calcDistance(nb, target);
        return da < db;
    }
};

//用法
std::sort(m_dataList.begin(), m_dataList.end(), YxObjectLessThan(val));

<think>好的,用户想在PostgreSQL中计算字符串相似度,具体提到了Levenshtein和similarity函数。我需要先回忆一下PostgreSQL的相关函数。 首先,Levenshtein距离是用来衡量两个字符串之间的差异,即需要多少次单字符编辑(插入、删除、替换)才能让两个字符串相同。PostgreSQL确实有levenshtein函数,但可能需要安装fuzzystrmatch扩展。记得用户需要先执行CREATE EXTENSION fuzzystrmatch;来启用这个功能。然后使用levenshtein(string1, string2)来计算距离,值越小越相似。例如levenshtein('kitten', 'sitting')会返回3,因为需要替换k为s,替换e为i,加上g,共三次编辑[^1]。 然后是similarity函数,这可能涉及到pg_trgm扩展。pg_trgm将字符串分解为三个字符的序列,通过比较这些序列的重叠程度来计算相似度。用户需要安装pg_trgm,同样使用CREATE EXTENSION pg_trgm;。之后可以用similarity(string1, string2),结果在0到1之间,越接近1越相似。比如similarity('cat', 'cats')可能返回0.75,因为三个字母中有三个匹配,加上一个字符的差异[^2]。另外,用户提到的word_similarity函数可能更适合部分匹配的情况,比如子字符串相似度,这在查询中可能更高效,尤其是处理长文本时。 用户可能还关心实际应用,比如如何结合这些函数进行查询。例如,查找相似度大于某个阈值的结果并按相似度排序,这需要用到WHERE子句和ORDER BY。例如SELECT * FROM table WHERE similarity(column, 'query') > 0.5 ORDER BY similarity DESC LIMIT 10; 这样就能得到最相似的前十条记录[^2]。此外,Levenshtein距离可以转化为相似度百分比,比如用(max_len - distance)/max_len * 100,这在引用3中提到的Python示例里有类似的处理方法,可能用户想了解如何在PostgreSQL中实现类似的转换。 另外,性能方面需要考虑,使用pg_trgm的similarity可能会创建GIN或GiST索引来加速查询,尤其是在大数据量的情况下。而Levenshtein函数可能没有索引支持,全表扫描会影响性能,所以适用于小规模数据。 用户可能的应用场景包括数据清洗、模糊搜索或拼写纠正。例如,在用户输入错误时,通过计算相似度找到最接近的正确选项。或者合并数据库中重复的记录,比如名字拼写略有不同的客户信息。 需要提醒用户注意,不同的函数适用于不同的场景:Levenshtein适合精确的编辑距离,而similarity基于三元组,更适合处理自然语言文本中的部分匹配。同时,安装扩展是必要的前提步骤,可能涉及到数据库权限的问题,需要确保有权限执行CREATE EXTENSION。 最后,可能需要给出具体的示例,帮助用户理解如何实际应用这些函数。比如同时展示Levenshtein距离计算和转换为相似度百分比的方法,以及similarity函数的查询示例,这样用户可以直接参考使用。</think>在PostgreSQL中计算字符串相似度主要有两种常用方法:基于编辑距离的$Levenshtein$函数和基于三元组的$similarity$函数。以下是具体实现方法: ### 一、Levenshtein编辑距离 1. **安装扩展**(需超级用户权限): ```sql CREATE EXTENSION fuzzystrmatch; ``` 2. **基本用法**: $$Levenshtein(\text{string1}, \text{string2}) \rightarrow \text{integer}$$ 计算两个字符串的最小单字符编辑次数。例如: ```sql SELECT levenshtein('kitten', 'sitting'); -- 返回3[^1] ``` 3. **转换为相似度百分比**: $$similarity = \frac{\max(len1, len2) - distance}{\max(len1, len2)} \times 100$$ ```sql SELECT (GREATEST(LENGTH('apple'), LENGTH('apples')) - levenshtein('apple', 'apples')) * 100.0 / GREATEST(LENGTH('apple'), LENGTH('apples')) AS similarity; ``` ### 二、pg_trgm相似度 1. **安装扩展**: ```sql CREATE EXTENSION pg_trgm; ``` 2. **基本函数**: $$similarity(\text{string1}, \text{string2}) \rightarrow \text{float}[0-1]$$ ```sql SELECT similarity('cat', 'cats'); -- 返回0.75 ``` 3. **高级查询示例**: ```sql SELECT tokens, word_similarity(tokens, '查询词') AS score FROM mytable WHERE word_similarity(tokens, '查询词') > 0.4 ORDER BY score DESC LIMIT 10; ``` ### 三、性能优化建议 1. 对$pg\_trgm$创建GIN索引: ```sql CREATE INDEX idx_tokens_gin ON mytable USING GIN (tokens gin_trgm_ops); ``` 2. 对长文本优先使用$word\_similarity$函数,其采用子字符串最优匹配算法,性能优于全文本比较。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值