当前位置: 首页 > news >正文

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库配置

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

相关文章:

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

diff库介绍 diff 库是基于 Myers 差分算法 实现的 JavaScript 文本差异库。 Myers 差分算法 是由 Eugene Myers 在 1986 年发表的一篇经典算法论文 “An O(ND) Difference Algorithm and its Variations” 中描述的一种高效算法&#xff0c;用于计算两个序列&#xff08;通常是…...

自动驾驶3D目标检测综述(六)

停更了好久终于回来了&#xff08;其实是因为博主去备考期末了hh&#xff09; 这一篇接着&#xff08;五&#xff09;的第七章开始讲述第八章的内容。第八章主要介绍的是三维目标检测的高效标签。 目录 第八章 三维目标检测高效标签 一、域适应 &#xff08;一&#xff09;…...

the request was rejected because no multipart boundary was found

文章目录 1. 需求描述2. 报错信息3. 探索过程 1. 使用postman 排除后端错误2. 搜索网上的解决方法3. 解决方法 1. 需求描述 想要在前端上传一个PDF 发票&#xff0c;经过后端解析PDF之后&#xff0c;将想要的值自动回填到对应的输入框中 2. 报错信息 org.apache.tomcat.u…...

HarmonyOS-面试整理

目录 为什么选择HarmonyOS/ 优点/特点鸿蒙系统的权限有哪些说一说鸿蒙系统的安全机制说一说鸿蒙系统的微内核与安卓的内核区别鸿蒙操作系统的微内核架构有哪些优势分布式能力在鸿蒙系统中如何实现请解释一下鸿蒙系统中的分布式软总线技术如何在鸿蒙操作系统中进行多设备协同开发…...

[C#] 「Unity」「游戏开发」如何在Canvas下的Button控件下实例化Image元素

在开发过程中,经常需要在UI上动态添加元素。特别是在Unity中,Canvas控件通常用来作为UI元素的容器,而Button控件则常用于交互。而在某些情况下,我们可能需要在一个Button下实例化一个Image元素,并确保它的位置与Button的位置保持一致。然而,简单地使用Button的坐标值往往…...

Nginx1.20.2-Linux-安装

文章目录 1.下载压缩包1.官网下载2.找到1.20.23.百度网盘 2.Linux安装1.搭建gcc环境2.上传到 /usr/local/nginx1.20.23.解压1.解压到当前目录2.删除压缩包 4.配置Nginx的编译路径1.进入nginx-1.20.22.执行内部的脚本&#xff0c;指定编译路径为/usr/local/nginx 5.编译并安装6.…...

Elasticsearch名词解释

文章目录 1.什么是Elasticsearch?2.什么是elastic stack(ELK)?3.什么是Lucene?4.什么是文档(document)&#xff1f;5.什么是词条(term)&#xff1f;6.什么是正向索引&#xff1f;7.什么是倒排索引&#xff1f;8.ES中的索引(index)9.映射(Mapping)10.DSL11.elastcisearch与my…...

Node项目——从0开始构建且共享至Gitee

从0开始构建一个Node.js项目涉及多个步骤&#xff0c;包括设置开发环境、初始化项目、安装依赖、编写代码以及配置版本控制等。以下是一个详细的步骤指南&#xff1a; 1. 安装Node.js和npm 首先&#xff0c;确保你已经安装了Node.js和npm&#xff08;Node Package Manager&am…...

layui多图上传,tp8后端接收处理

环境&#xff1a;layui2.9.21\thinkphp8.1 前端代码&#xff1a; layui.use([upload, layer], function() {const upload layui.upload;const layer layui.layer;const $ layui.$;// 上传图片const uploadInstImage upload.render({elem: #uploadImage,url: /admin/demo/…...

QEMU网络配置简介

本文简单介绍下qemu虚拟机网络的几种配置方式。 通过QEMU的支持&#xff0c;常见的可以实现以下4种网络形式&#xff1a; 基于网桥&#xff08;bridge&#xff09;的虚拟网络。基于NAT&#xff08;Network Addresss Translation&#xff09;的虚拟网络。QEMU内置的用户模式网…...

28.Marshal.PtrToStringAnsi C#例子

//怎么说呢&#xff0c;这个代码Marshal的英文意思有将军&#xff0c;控制等等&#xff0c; //我的理解是类似于console控制台。 //然后后面这个Ansi是一种ASCII的扩展&#xff0c;还有其他编码方式可选 就是一个把后面的指针转化为字符串的一个代码 这是用法…...

基于feapder爬虫与flask前后端框架的天气数据可视化大屏

# 最近又到期末了&#xff0c;有需要的同学可以借鉴。 一、feapder爬虫 feapder是国产开发的新型爬虫框架&#xff0c;具有轻量且数据库操作方便、异常提醒等优秀特性。本次设计看来利用feapder进行爬虫操作&#xff0c;可以加快爬虫的速率&#xff0c;并且简化数据入库等操作…...

Linux隐藏登录和清除历史命令以及其他相关安全操作示例

隐藏登录 ssh -T rootxxx.xxx.xxx.xxx /bin/bash -i 命令拆解-T &#xff1a;告诉ssh客户端&#xff0c;不要分配一个TTY&#xff08;伪终端&#xff09;root &#xff1a;连接用户xxx.xxx.xxx.xxx &#xff1a;连接的服务器ip地址/bin/bash &#xff1a;在远程服务器上启动…...

从授权校验看SpringBoot自动装配

背景 最近需要实现一个对于系统的授权检测功能&#xff0c;即当SpringBoot应用被启动时&#xff0c;需要当前设备是否具有有效的的授权许可信息&#xff0c;若无则直接退出应用。具体的实现方案请继续看下文。 环境 Ruoyi-Vue SpringBoot3 RuoYi-Vue: &#x1f389; 基于Spr…...

tensorboard的界面参数与图像数据分析讲解

目录 1.基础概念&#xff1a; (a)精确率与召回率&#xff1a; (b)mAP: (c)边界框损失&#xff1a; (d)目标损失&#xff1a; (e)分类损失&#xff1a; (f):学习率&#xff1a; 2.设置部分&#xff08;最右边部分&#xff09;&#xff1a; GENERAL&#xff08;常规设置…...

MTK 平台关于WIFI 6E P2P的解说

一 前言 官方 P2P 6E 设计原理,请查看这个网站 hostap - hostapd/wpa_supplicant 配置:p2p_6ghz_disable 允许上层指定是否允许6G连接 仅允许6G用于WFD –不允许6G用于纯P2P 缺点:存在很多 IOT issues 如:一些物联网设备无法识别6G类/信道,可能存在物联网问…...

离线语音识别+青云客语音机器人(幼儿园级别教程)

1、使用步骤 确保已安装以下库&#xff1a; pip install vosk sounddevice requests pyttsx3 2、下载 Vosk 模型&#xff1a; 下载适合的中文模型&#xff0c;如 vosk-model-small-cn-0.22。 下载地址&#xff1a; https://alphacephei.com/vosk/models 将模型解压后放置在…...

leetcode hot 100 跳跃游戏

55. 跳跃游戏 已解答 中等 相关标签 相关企业 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则…...

陪诊陪护助浴系统源码:JAVA养老护理助浴陪诊小程序医院陪护陪诊小程序APP源码

JAVA养老护理助浴陪诊小程序及医院陪护陪诊APP&#xff1a;打造智慧养老新生态 在人口老龄化日益加剧的当下&#xff0c;养老护理服务的需求日益增长&#xff0c;而传统的养老服务模式已难以满足日益多样化的需求。为此&#xff0c;我们基于JAVA技术栈&#xff0c;精心打造了一…...

怎么在家访问公司服务器?

在日常工作中&#xff0c;特别是对信息技术从业者而言&#xff0c;工作往往离不开公司的服务器。他们需要定期访问服务器&#xff0c;获取一些关键的机密文件或数据。如果您在家办公&#xff0c;并且需要处理未完成的任务&#xff0c;同时需要从公司服务器获取所需的数据&#…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

简单介绍C++中 string与wstring

在C中&#xff0c;string和wstring是两种用于处理不同字符编码的字符串类型&#xff0c;分别基于char和wchar_t字符类型。以下是它们的详细说明和对比&#xff1a; 1. 基础定义 string 类型&#xff1a;std::string 字符类型&#xff1a;char&#xff08;通常为8位&#xff09…...