Diff : le calcul de différences omniprésent
De la gestion de versions Git à la revue de code, des changements de configuration à la synchronisation de données — Diff est une opération fondamentale du développement logiciel.
| Scénario |
Type de Diff |
Outil |
| Changements de code |
Diff par ligne |
Git |
| Comparaison de configuration |
Diff par clé-valeur |
Outil de comparaison en ligne |
| Données JSON |
Diff structuré |
json-diff |
| Documents juridiques |
Diff sémantique |
Outil spécialisé |
| Vérification de traduction |
Diff par caractère |
Comparaison en ligne |
I. Principes de l'algorithme Myers Diff
Idée centrale
L'algorithme Myers recherche le script d'édition le plus court (SES) qui convertit le texte source en texte cible — le moins d'opérations d'insertion/suppression.
Source : ABCABBA
Cible : CBABAC
Script d'édition :
- A (supprimer A)
B (conserver B)
- C (supprimer C)
C (conserver C → insérer C avant)
A (conserver A)
B (conserver B)
- B (supprimer B)
A (conserver A)
+ C (insérer C)
Diagramme de l'algorithme
0 1 2 3 4 5 6 7
┌───┬───┬───┬───┬───┬───┬───┬───┐
0 │ → │ ↘ │ │ │ │ │ │ │ A
├───┼───┼───┼───┼───┼───┼───┼───┤
1 │ ↓ │ │ ↘ │ │ → │ ↘ │ │ │ B
├───┼───┼───┼───┼───┼───┼───┼───┤
2 │ │ ↓ │ │ ↘ │ ↓ │ │ ↘ │ │ C
├───┼───┼───┼───┼───┼───┼───┼───┤
3 │ │ │ ↓ │ │ │ ↓ │ │ ↘ │ A
├───┼───┼───┼───┼───┼───┼───┼───┤
4 │ │ │ │ ↓ │ ↘ │ │ ↓ │ │ B
├───┼───┼───┼───┼───┼───┼───┼───┤
5 │ │ │ │ │ ↓ │ │ │ ↓ │ B
├───┼───┼───┼───┼───┼───┼───┼───┤
6 │ │ │ │ │ │ ↓ │ ↘ │ │ A
└───┴───┴───┴───┴───┴───┴───┴───┘
C B A B A C B A
→ = droite (supprimer) ↓ = bas (insérer) ↘ = diagonale (conserver)
Complexité temporelle
| Cas |
Complexité |
Description |
| Optimal |
O(ND) |
N=longueur du texte, D=nombre de différences |
| Pire |
O((N+M)D) |
Textes complètement différents |
| Typique |
O(N+D²) |
Peu de différences |
II. Utilisation de l'outil de comparaison de texte de Tools Ku
Étapes de fonctionnement
- Ouvrez l'Outil de comparaison de texte
- Collez le texte original à gauche
- Collez le texte modifié à droite
- Consultez les résultats des différences :
- Rouge : lignes supprimées
- Vert : lignes ajoutées
- Jaune : lignes modifiées
- Prend en charge la mise en évidence par caractère, précise jusqu'à chaque changement de caractère
Modes de comparaison
| Mode |
Granularité |
Cas d'utilisation |
| Par ligne |
Comparaison par ligne |
Changements de code |
| Par mot |
Comparaison par mot |
Révisions de documents |
| Par caractère |
Comparaison par caractère |
Correction précise |
III. Techniques spéciales de JSON Diff
Utilisation de l'outil JSON Diff
- Ouvrez l'Outil JSON Diff
- Collez deux données JSON
- Consultez les différences structurées :
- Clés ajoutées/supprimées/modifiées
- Changements de valeurs (y compris changements de type)
- Chemins imbriqués
JSON Diff vs Diff textuel
// Original
{ "name": "张三", "age": 25, "tags": ["a", "b"] }
// Modifié
{ "name": "张三", "age": 26, "tags": ["a", "c"], "email": "z@test.com" }
| Méthode de comparaison |
Résultat |
| Diff textuel |
Affiche les différences par ligne, difficile à comprendre |
| JSON Diff |
age: 25→26, tags[1]: "b"→"c", +email: "z@test.com" |
--- a/config.json
+++ b/config.json
@@ -1,5 +1,6 @@
{
"name": "my-project",
- "version": "1.0.0",
+ "version": "2.0.0",
"description": "A tool",
- "private": true
+ "private": true,
+ "license": "MIT"
}
| Symbole |
Signification |
--- |
Fichier original |
+++ |
Fichier modifié |
@@ -a,b +c,d @@ |
Position de la différence (original à partir de la ligne a, b lignes ; modifié à partir de la ligne c, d lignes) |
- |
Ligne supprimée |
+ |
Ligne ajoutée |
(espace) |
Ligne de contexte |
V. Génération et application de correctifs
Générer un correctif
import * as Diff from 'diff';
const oldText = 'Hello World\nGoodbye World';
const newText = 'Hello World\nGoodbye Cruel World';
// Générer le correctif
const patch = Diff.createPatch('file.txt', oldText, newText, 'old', 'new');
console.log(patch);
Sortie :
--- old/file.txt
+++ new/file.txt
@@ -1,2 +1,2 @@
Hello World
-Goodbye World
+Goodbye Cruel World
Appliquer un correctif
// Application en avant
const result = Diff.applyPatch(oldText, patch);
// Application en inverse (retour arrière)
const reversed = Diff.applyPatch(newText, Diff.reversePatch(patch));
Fusion à trois
const base = 'Texte original';
const branchA = 'Modification de A';
const branchB = 'Modification de B';
const merged = Diff.mergeDiff3(base, branchA, branchB);
// Fusion automatique, les conflits sont marqués avec <<<<<<< / ======= / >>>>>>>
VI. Scénarios d'application pratique
Détection de changements dans les fichiers de configuration
const oldConfig = JSON.parse(fs.readFileSync('config.old.json', 'utf-8'));
const newConfig = JSON.parse(fs.readFileSync('config.new.json', 'utf-8'));
const diff = Diff.diffJson(oldConfig, newConfig);
diff.forEach(part => {
if (part.added) console.log('Ajouté :', JSON.stringify(part.value, null, 2));
if (part.removed) console.log('Supprimé :', JSON.stringify(part.value, null, 2));
});
Vérification des fichiers de traduction
// Comparer la cohérence des clés de traduction chinois-anglais
const zhKeys = Object.keys(flatten(zhTranslation));
const enKeys = Object.keys(flatten(enTranslation));
const missingInEn = zhKeys.filter(k => !enKeys.includes(k));
const missingInZh = enKeys.filter(k => !zhKeys.includes(k));
Tests de régression des réponses d'API
const expected = await fs.readFile('fixtures/expected.json', 'utf-8');
const actual = await fetch('/api/data').then(r => r.json());
const diff = Diff.diffJson(JSON.parse(expected), actual);
if (diff.some(d => d.added || d.removed)) {
throw new Error('La réponse de l\'API ne correspond pas à l\'attendu');
}
| Stratégie d'optimisation |
Effet |
Applicable à |
| Limiter les lignes de contexte |
Réduit la taille de sortie |
Fichiers volumineux |
| Prétraitement par hachage |
Ignore les lignes identiques |
Très gros fichiers |
| Comparaison par blocs |
Traitement parallèle |
Textes très longs |
| Niveau ligne avant niveau caractère |
Réduit la charge de calcul |
Fichiers de code |
// Limiter les lignes de contexte
const patch = Diff.createPatch('file', old, new, '', '', { context: 3 });