JavaScript的diff库详解(示例:vue项目实现两段字符串比对标黄功能)

diff库介绍

diff 库是基于 Myers 差分算法 实现的 JavaScript 文本差异库。
Myers 差分算法 是由 Eugene Myers 在 1986 年发表的一篇经典算法论文 “An O(ND) Difference Algorithm and its Variations” 中描述的一种高效算法,用于计算两个序列(通常是字符串)之间的差异。

该算法的时间复杂度为 O(ND),其中:

  • N 是两个序列中较短序列的长度。
  • D 是两个序列之间的最小编辑距离,即从一个序列变换为另一个序列所需的最少操作次数(插入、删除或替换)。

通过该算法,diff 库可以高效地分析文本之间的差异,广泛应用于文本比对、版本管理和实时内容编辑等场景。


在线演示文档

diff 库提供了一个在线演示网站,方便用户了解其功能:https://kpdecker.github.io/jsdiff

基于在线演示网站,我们可以看到diff 库支持字符级词级行级unified diff等等的差异比较。

前面三个都好理解,unified diff则可能需要了解下相应概念。

Unified Diff 和 Patch 的概念

Unified Diff

Unified Diff 是一种标准化的差异格式,用于描述两个文本文件之间的变化,广泛使用于版本控制系统(如 Git)。它通过行号和上下文信息展示新增、删除或修改的内容,是 diff 工具生成的输出格式之一。

一个 Unified Diff 的典型结构如下:

--- oldFile.txt
+++ newFile.txt
@@ -1,4 +1,4 @@Line 1
-Line 2
+Line 2 updatedLine 3Line 4

解释:

--- oldFile.txt 和 +++ newFile.txt:分别表示旧文件和新文件的文件名。
@@ -1,4 +1,4 @@:上下文范围的描述。
-1,4 表示旧文件从第 1 行开始的 4 行。
+1,4 表示新文件从第 1 行开始的 4 行。
- 表示从旧文件中移除的内容。
+ 表示添加到新文件中的内容。

Patch

Patch 是应用这些差异的一种工具,通常配合 Unified Diff 使用。patch 工具可以读取 Unified Diff 格式的文件,并将其应用到目标文件上,以实现对文件的更新。

diff 库中的 createPatch 方法生成的就是一个 Unified Diff 格式的输出。可以用这个输出作为输入,再使用 applyPatch 方法将这些差异应用到目标文本中。


diff库比对的基本流程

diff 库的所有diff函数都用于比较两个文本,并执行以下三个步骤:

1. 将文本分割为 “tokens”

  • Token 的定义:Token 是文本中的最小单位,其定义根据所使用的 diff 方法而变化:
    • diffChars 方法中,每个字符是一个token。
    • diffWords 方法中,每个单词是一个token。
    • diffLines 方法中,每一行是一个token。

通过这种分割方式,diff 库能够灵活地比较文本的不同层次(如字符、单词或行)。


2. 找到最小的操作集合

  • 目标:通过最少的插入和删除操作,将第一个 token 数组转换为第二个 token 数组。
  • 相等的定义
    • 默认情况下,两个 token 是否相等由 === 运算符决定。
    • 某些 diff 方法支持自定义“相等”定义。例如:
      • 默认比较中,diffChars("Foo", "FOOD") 会认为 oO 不相等:
        • 结果:删除两个 o,插入两个 O 和一个 D
      • 设置选项 { ignoreCase: true } 后,oO 会被视为相等:
        • 结果:仅需要插入一个 D

3. 返回变换结果

  • 返回值:一个数组,表示从旧文本到新文本的转换过程。
    • 数组结构:包含一系列 change objects
    • 顺序:从输入的起始位置到结束位置按顺序排列。
    • change objects 的含义
      • 插入:在新文本中添加一个或多个 token(added: true)。
      • 删除:从旧文本中删除一个或多个 token(removed: true)。
      • 保留:保持一个或多个 token 不变(无 addedremoved 标记)。

示例代码

以下是 diffChars 的一个简单示例:

import { diffChars } from 'diff';const oldText = "Foo";
const newText = "FOOD";// 默认比较(区分大小写)
const result = diffChars(oldText, newText);
console.log(result);
/* 数据格式
[{ value: 'F', count: 1 },{ removed: true, value: 'o' },{ removed: true, value: 'o' },{ added: true, value: 'O' },{ added: true, value: 'O' },{ added: true, value: 'D' }
]
*/// 忽略大小写
const resultIgnoreCase = diffChars(oldText, newText, { ignoreCase: true });
console.log(resultIgnoreCase);
/* 数据格式
[{ value: 'Foo', count: 3 },{ added: true, value: 'D' }
]
*/

diff 库安装与使用

1. 安装库

通过 npm 安装:

npm install --save diff

2. 在项目中导入

在 Vue 项目中,可以通过以下方式引入库中所需的功能:

import { diffWords } from 'diff';

3. 在 Vue 项目中使用

在 Vue 项目中,可以将比对函数与 v-html 指令结合,动态渲染高亮比对的结果。

组件模板
<template><div v-html="getYellowDiffText(tableName1, tableName2)"></div>
</template>
组件逻辑
<script>
import { diffWords } from 'diff';export default {data() {return {tableName1: 'Hello world!',tableName2: 'Hello my friend!',};},methods: {/** 比较两个字符串,标记差异部分为黄色,diff库比对结果状态只有added和removed,新增部分即存在差异部分 */getYellowDiffText(tableName1, tableName2) {let htmltext = '';let diffs = [];if (!tableName2) {diffs = [{ value: tableName1 }];} else {diffs = diffWords(tableName1, tableName2);}diffs.forEach((item) => {htmltext += item.added? `<span style="background-color: yellow;">${item.value}</span>`: item.removed? '' // 个人项目需求不需要比对删除情况,有需求的可以自行处理: item.value;});return htmltext;},},
};
</script>

diff库api

  • Diff.diffChars(oldStr, newStr[, options]) - diffs 两个文本块,将每个字符视为一个标记。
  • Diff.diffWords(oldStr, newStr[, options]) - diff 两个文本块,将每个单词和每个标点符号视为一个标记。在计算 diff 时,将忽略空格(但在最终的 change 对象中尽可能保留)。
  • Diff.diffWordsWithSpace(oldStr, newStr[, options]) - diff 两个文本块,将每个单词、标点符号、换行符或连续(非换行符)空格视为一个标记。
  • Diff.diffLines(oldStr, newStr[, options]) - diff 两个文本块,将每一行视为一个标记。
  • Diff.diffSentences(oldStr, newStr[, options]) - diff 两个文本块,将每个句子视为一个标记。字符 .、 !和 ?后跟空格时,被视为标记句子的结尾;没有其他内容被视为标记句子结束。
  • Diff.diffCss(oldStr, newStr[, options]) - diffs 两个文本块,比较 CSS 令牌。
  • Diff.diffJson(oldObj, newObj[, options]) - 通过首先将两个 JSON 可序列化对象序列化为格式精美的 JSON,然后将 JSON 的每一行视为令牌,来区分这两个对象。对象属性在序列化的 JSON 中按字母顺序排序,因此被比较的对象中的属性顺序不会影响结果。
  • Diff.diffArrays(oldArr, newArr[, options]) - diff 两个标记数组,比较每个项的严格相等性 (===)。
  • Diff.createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr[, oldHeader[, newHeader[, options]]]) - 首先使用 diffLines 计算 diff,然后将其序列化为统一的 diff 格式,从而创建统一的 diff 补丁。

diff库配置

  • 可配置忽略空白字符、大小写等比较选项。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/501036.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双目视觉:reprojectImageTo3D函数

前言 reprojectImageTo3D 是 OpenCV 中用于从视差图生成三维点云的函数。它的原理是利用视差图和相机的校准参数&#xff0c;通过三角测量法&#xff0c;计算每个像素对应的三维坐标。以下内容根据源码分析所写&#xff0c;觉得可以的话&#xff0c;点赞收藏哈&#xff01;&am…

苍穹外卖04——Redis初入门 在店铺打烊or营业状态管理功能中的使用

Redis入门 redis简介 它以键值对的形式存储数据在内存中,并且以极高的性能和灵活性而著称,通常用于缓存、消息代理以及持久化数据。 - 基于内存存储,读写性能高- 适合存储热点数据(热点商品、资讯、新闻)- 企业应用广泛Windows版下载地址:https://github.com/microsoft…

No.1十六届蓝桥杯备战|第一个C++程序|cin和cout|命名空间

第一个C程序 基础程序 使用DevC5.4.0 写一个C程序 在屏幕上打印hello world #include <iostream> using namespace std;int main() {cout << "hello world" << endl;return 0; } 运行这个C程序 F9->编译 F10->运行 F11->编译运行 mai…

springboot实战(19)(条件分页查询、PageHelper、MYBATIS动态SQL、mapper映射配置文件、自定义类封装分页查询数据集)

引言&#xff1a; 该类博客的学习是基于b站黑马视频springbootvue视频学习&#xff01;具体围绕项目——"大事件"进行实战学习。 目录 一、功能介绍&#xff08;需求&#xff09;。 1、文章列表功能基本介绍。 2、条件分页查询功能与注意。 3、前端页面效果。&#x…

LoRA微调系列笔记

系列文章目录 第一章&#xff1a;LoRA微调系列笔记 第二章&#xff1a;Llama系列关键知识总结 第三章&#xff1a;LLaVA模型讲解与总结 文章目录 系列文章目录LoRA&#xff1a;Low-Rank Adaptation of Large Language Models目的&#xff1a;依据&#xff1a;优势&#xff1a;…

Python - 游戏:飞机大战;数字华容道

Pygame是一个利用SDL库的写的游戏库&#xff0c;SDL呢&#xff0c;全名Simple DirectMedia Layer&#xff0c;是一位叫做Sam Lantinga的大牛写的 SDL是用C写的&#xff0c;不过它也可以使用C进行开发&#xff0c;当然还有很多其它的语言&#xff0c;Pygame就是Python中使用它的…

【JVM】总结篇-字节码篇

字节码篇 Java虚拟机的生命周期 JVM的组成 Java虚拟机的体系结构 什么是Java虚拟机 虚拟机&#xff1a;指以软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统 &#xff0c;是物理机的软件实现。常用的虚拟机有VMWare&#xff0c;Visual Box&…

GitHub 及 GitHub Desktop 详细使用教程(通俗易懂)

目录 Δ前言 一、Github教程 1.什么是Github&#xff1f; 2.仓库和对仓库的操作&#xff1a; 2.1 Repository&#xff08;仓库&#xff09; 2.2 Fork&#xff08;派生&#xff09; 2.3 Star&#xff08;收藏&#xff09; 2.4 Watch&#xff08;追番&#xff09; 2.5 Issue&am…

OpenLinkSaas使用手册-待办事项和通知中心

在OpenLinkSaas工作台上&#xff0c;你可以查看待办事项和未读通知。 待办事项 目前待办事项支持: 个人待办项目待办:在项目中指派给你的任务/缺陷Git待办:在Git仓库中指标给你的Issue,目前只有在AtomGit和Gitee账号登录时才支持。 通知中心 通知中心支持Git通知和邮件通知两种…

springboot集成阿里云短信服务

springboot集成阿里云短信服务 一.阿里云账号准备 流程:注册阿里云账号>短信服务>新增资质>新建签名>新建模版>申请秘钥>用代码测试 1.注册阿里云账号 2、登录成功后&#xff0c; ① 在首页搜索短信服务 ② 打开第一个搜索结果 ③ 免费开通 ④ 可以根据…

试题转excel;word转excel;大风车excel(1.1更新)

最近更新了大风车excel1.1版本 主要优化在算法层面&#xff1a; 1.0版本试题解析的成功率为95%&#xff0c;现在1.1版本已经优化到解析成功率为99% 一、问题描述 一名教师朋友&#xff0c;偶尔会需要整理一些高质量的题目到excel中 以往都是手动复制搬运&#xff0c;几百道…

python实现自动登录12306抢票 -- selenium

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 python实现自动登录12306抢票 -- selenium 前言其实网上也出现了很多12306的代码&#xff0c;但是都不是最新的&#xff0c;我也是从网上找别人的帖子&#xff0c;看B站视频&…

机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型

机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型 目录 机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型1 过拟合和欠拟合1.1 过拟合1.2 欠拟合 2 正则化惩罚2.1 概念2.2 函数2.3 正则化种类 3 K折交叉验证3.1 概念3.2 图片理解3.3 函数导入3.4 参数理解 4 训练模型K折交…

文件本地和OSS上传

这里写目录标题 前端传出文件后端本地存储阿里云OSS存储上传Demo实现上传ConfigurationProperties 前端传出文件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>上传文件</title> </head&g…

《Vue3实战教程》37:Vue3生产部署

如果您有疑问&#xff0c;请观看视频教程《Vue3实战教程》 生产部署​ 开发环境 vs. 生产环境​ 在开发过程中&#xff0c;Vue 提供了许多功能来提升开发体验&#xff1a; 对常见错误和隐患的警告对组件 props / 自定义事件的校验响应性调试钩子开发工具集成 然而&#xff…

python制作打字小游戏

import pygame # 导入游戏模块 安装pygame import sys # 导入系统指令模块 import random # 导入随机数模块 pygame.init() #初始化游戏环境 wndpygame.display.set_mode((800,565)) #指定窗口大小 pygame.mixer.music.load(素材/SurvivalGame.mp3) #素…

抖音短视频矩阵系统源码开发全流程解析

在项目开发过程中&#xff0c;调整配置文件至关重要&#xff0c;这些文件包括数据库连接、API密钥及全局参数等。通过正确配置这些信息&#xff0c;可确保应用程序的稳定性和安全性。灵活调整配置以适应具体需求有助于短视频矩阵系统项目的顺利推进。 在开发环境中&#xff0c…

前端路由layout布局处理以及菜单交互(三)

上篇介绍了前端项目部署以及基本依赖的应用&#xff0c;这次主要对于路由以及布局进行模块化处理 一、 创建layout模块 1、新建src/layout/index.vue <template><el-container class"common-layout"><!-- <el-aside class"aside">&l…

戴尔/Dell 电脑按什么快捷键可以进入 Bios 设置界面?

BIOS&#xff08;基本输入输出系统&#xff09;是计算机硬件与操作系统之间的桥梁&#xff0c;它负责初始化和测试系统硬件组件&#xff0c;并加载启动操作系统。在某些情况下&#xff0c;如调整启动顺序、更改系统时间或日期、修改硬件配置等&#xff0c;您可能需要进入BIOS进…

《从入门到精通:蓝桥杯编程大赛知识点全攻略》(一)-递归实现指数型枚举、递归实现排列型枚举

本篇博客将聚焦于通过递归来实现两种经典的枚举方法&#xff1a;指数型枚举和排列型枚举。这两种枚举方式在计算机科学和算法竞赛中都有广泛应用&#xff0c;无论是在解题中&#xff0c;还是在实际工作中都极具价值。 目录 前言 斐波那契数列递归 递归实现指数型枚举 算法思…