给定2个字符,计算字符串发生了那些变化(插入、删除、替换)

import { insert, remove, update } from "ramda";
// 计算差异度
export function levenshteinDistance<T = any>(a: T[],b: T[],compose: (a: T, b: T) => boolean = (a, b) => a === b
): number {return levenshteinDistanceMatrix(a, b, compose)[b.length][a.length];
}
// 计算差异矩阵,详见算法levenshtein distance
export function levenshteinDistanceMatrix<T = any>(a: T[],b: T[],compose: (a: T, b: T) => boolean = (a, b) => a === b
): number[][] {const distanceMatrix = Array(b.length + 1).fill(null).map(() => Array(a.length + 1).fill(null));for (let i = 0; i <= a.length; i += 1) {distanceMatrix[0][i] = i;}for (let j = 0; j <= b.length; j += 1) {distanceMatrix[j][0] = j;}for (let j = 1; j <= b.length; j += 1) {for (let i = 1; i <= a.length; i += 1) {const indicator = compose(a[i - 1],b[j - 1])? 0: 1;const min = Math.min(distanceMatrix[j][i - 1] + 1,distanceMatrix[j - 1][i] + 1,distanceMatrix[j - 1][i - 1] + indicator);distanceMatrix[j][i] = min;}}return distanceMatrix;
}
// 字符串变化类型
export enum LevenshteinOperatorType {// 删除deletion,// 插入insertion,// 替换substitution
}
// 删除数据结构
export interface LevenshteinDeletion<T = any> {type: LevenshteinOperatorType.deletion;index: number;value: T;
}
// 插入数据结构
export interface LevenshteinInsertion<T = any> {type: LevenshteinOperatorType.insertion;index: number;value: T;
}
// 替换数据结构
export interface LevenshteinSubstitution<T = any> {type: LevenshteinOperatorType.substitution;index: number;value: {old: T;new: T;};
}export type LevenshteinOperator<T = any> =| LevenshteinDeletion<T>| LevenshteinInsertion<T>| LevenshteinSubstitution<T>;
//是否删除
export function isLevenshteinDeletion<T = any>(val: LevenshteinOperator<T>
): val is LevenshteinDeletion<T> {return val.type === LevenshteinOperatorType.deletion;
}
// 是否插入
export function isLevenshteinInsertion<T = any>(val: LevenshteinOperator<T>
): val is LevenshteinInsertion<T> {return val.type === LevenshteinOperatorType.insertion;
}
// 是否替换
export function isLevenshteinSubstitution<T = any>(val: LevenshteinOperator<T>
): val is LevenshteinSubstitution<T> {return val.type === LevenshteinOperatorType.substitution;
}
// 默认最大值
const max = 9999999999;
export function levenshteinOperators<T = any>(a: T[],b: T[],compose: (a: T, b: T) => boolean = (a, b) => a === b
): LevenshteinOperator<T>[] {const res = levenshteinDistanceMatrix<T>(a, b, compose);// const dd = res.map(col => `|${col.join("|")}|`);// console.log(`${dd.join("\n")}`);// 求最小值坐标let i = b.length; // 行let j = a.length; //列let copy = a;let operators: LevenshteinOperator<T>[] = [];while (i > 0 || j > 0) {let deletion = max,insertion = max,substitution = max;const indicator = res[i][j];if (j > 0) {deletion = res[i][j - 1];}if (i > 0) {insertion = res[i - 1][j];}if (i > 0 && j > 0) {substitution = res[i - 1][j - 1];}const min = Math.min(deletion, insertion, substitution);if (min === insertion) {if (min !== indicator) {operators.push({type: LevenshteinOperatorType.insertion,value: b[i - 1],index: j - 1});}i -= 1;} else if (min === substitution) {if (min !== indicator) {operators.push({type: LevenshteinOperatorType.substitution,value: { old: a[j - 1], new: b[i - 1] },index: j - 1});}i -= 1;j -= 1;} else if (min === deletion) {if (min !== indicator) {operators.push({type: LevenshteinOperatorType.deletion,value: a[j - 1],index: j - 1});}j -= 1;}}return operators;
}
// 根据操作符,生成目标字符串
export function levenshteinTest<T>(a: T[],operators: LevenshteinOperator<T>[]
) {operators.map(opt => {if (isLevenshteinDeletion(opt)) {a = remove(opt.index, 1, a);}if (isLevenshteinInsertion(opt)) {a = insert(opt.index, opt.value, a);}if (isLevenshteinSubstitution(opt)) {a = update(opt.index, opt.value.new, a);}});return a;
}
复制代码
import { expect } from "chai";
import {levenshteinOperators,isLevenshteinSubstitution
} from "./levenshteinDistance";const a = `let item = 2;`;
const b = `let item = 3;`;
const ops = levenshteinOperators(a.split(""), b.split(""));describe("", () => {it("", () => {// 操作步骤长度为1expect(ops.length).equal(1);// 是替换操作符expect(isLevenshteinSubstitution(ops[0])).equal(true);// 将2替换为3expect((ops[0] as LevenshteinSubstitution).value.old).equal("2");expect((ops[0] as LevenshteinSubstitution).value.new).equal("3");});
});
复制代码

例子

levenshteinDistance

0 1 2 3 4 5
1 【2】插入112 2 3 4 5
2 【2】插入, 2 3 4 5
3 【3】插入223 3 3 4 5
4 【4】插入, 4 4 4 5
5 【4】不变let 5 5 5 5
6 5 【4】不变item 5 6 6
7 6 5 【4】不变= 5 6
8 7 6 5 【5】替换233->2 6
9 8 7 6 6 【5】不变;

const old = "let item = 233;"; const newStr = "112,223,let item = 2;";

给定2个字符串,如何计算变化(插入、删除、替换)?【levenshtein distance 算法】相关推荐

  1. 字符串相似度算法——Levenshtein Distance算法

    Levenshtein Distance 算法,又叫 Edit Distance 算法,是指两个字符串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一 ...

  2. 字符串操作:插入,替换,填充及移除

    字符串操作系列 本次涉及插入,替换,移除和填充几个操作. 1.插入(Insert) Insert(int startIndex,string value) :用于在一个字符串中的指定起始索引处插入另外 ...

  3. 可变字符串 插入,删除,替换,赋值

    NSString *str=@"welcome to oc";//字符串常量不能放在可变字符串中,应该放在不可变的字符串中 mustr=[NSMutableString strin ...

  4. 0202插入删除-算法第四版红黑树-红黑树-数据结构和算法(Java)

    文章目录 4 插入 4.1 序 4.2 向单个2-结点插入新键 4.3 向树底部的2-结点插入新键 4.4 向一棵双键树(3-结点)中插入新键 4.5 颜色调整 4.6 根结点总是黑色 4.7 向树底 ...

  5. python列表(list)+索引切片+修改+插入+删除+range函数生成整数列表对象

    python列表(list)+索引切片+修改+插入+删除+range函数生成整数列表对象 列表(list)是什么? 列表是Python中内置有序.可变序列,列表的所有元素放在一对中括号"[] ...

  6. 进程句柄表初始化,扩展,插入删除句柄源码分析

    一.为什么要有句柄 句柄是一个8字节的结构体,用途是指向内核对象.3环程序无法通过地址直接访问内核对象,所以需要用句柄来间接访问. 本文重点介绍句柄表,句柄本身则留到下一篇博客介绍.但因为接下来介绍句 ...

  7. 算法61---两个字符串的最小ASCII删除和【动态规划】

    一.题目: 给定两个字符串s1, s2,找到使两个字符串相等所需删除字符的ASCII值的最小和. 示例 1: 输入: s1 = "sea", s2 = "eat" ...

  8. leetcode712. 两个字符串的最小ASCII删除和(动态规划)-Gogo

    给定两个字符串s1, s2,找到使两个字符串相等所需删除字符的ASCII值的最小和. 示例 1: 输入: s1 = "sea", s2 = "eat" 输出: ...

  9. LeetCode 712. 两个字符串的最小ASCII删除和(DP,类似编辑距离)

    1. 题目 给定两个字符串s1, s2,找到使两个字符串相等所需删除字符的ASCII值的最小和. 示例 1: 输入: s1 = "sea", s2 = "eat" ...

最新文章

  1. 在WebStorm里面搜索文件中出现的中文字符
  2. ORACLE ERP 的前世今生(5)
  3. linux Rootkit:x86与ARM的内联内核函数Hooking
  4. 关于 \8 为56问题解答
  5. Vscode解决Setting.json报警告:Problems loading reference ... Unable to load schema from ...
  6. javascript获取asp.net后台代码的方法
  7. Android之ndk之gdb调试
  8. Larbin源代码分析[6]LARBIN中线程处理类
  9. Java学习笔记-正则表达式的模式匹配
  10. 深圳大学计算机考研复习资料百度云,深圳大学(专业学位)计算机技术研究生考试科目和考研参考书目...
  11. [转载] python json 编码(dump/dumps:字典转化为json)、解码(load/loads:json转化为字典)
  12. 【三维路径规划】基于matlab改进差分算法多无人机协同三维路径规划【含Matlab源码 169期】
  13. win7+VS2008安装boost
  14. 数据库表文档生成工具screw (螺丝钉)
  15. 学编程考计算机二级,如何通过计算机一、二级考试?方法很重要,过来人的经验告诉你...
  16. 软件首次亮相前超级账本技术升温
  17. redis之十五(游标迭代器(过滤器)——Scan)
  18. #第七章 双波不干涉理论 ​一、双波不干涉理论的分级方法
  19. Unity接入Google登录
  20. MultipartFile 转换为File

热门文章

  1. 计算机控制系统的理论,计算机控制系统理论基础.pptx
  2. Golang unsafe.Pointer指针
  3. 崔巍 计算机考研怎么样,中国科学院大学研究生导师教师师资介绍简介-崔巍
  4. 亮剑.NET. 图解C#开发实战 在线阅读
  5. 一件有趣的事:用Python爬了自己的微信朋友圈
  6. bzoj1207(HNOI2004)打鼹鼠
  7. oracle 连接查询--内连接与外连接
  8. Windows Mobile与OPhone开发对比
  9. archsummit2017见闻和思考
  10. largest-rectangle-in-histogram