Optimalizace diffu
Optimalizace diffu
Tento průvodce ukazuje, jak vyčistit surový diff — seznam DiffOperation hodnot (viz Diff jak jsou tyto vytvářeny) — do kanonické, minimální podoby pomocí post-processing průchodů v DiffOptimization pod-jmenném prostoru. Každý průchod implementuje IDiffOptimizationOperation a mění seznam diffů na místě, takže průchody lze řetězit v sekvenci a postupně zjednodušovat výsledek.
Smlouva o optimalizaci
IDiffOptimizationOperation definuje jedinou metodu, Execute(diffs), která normalizuje mutovatelný seznam hodnot DiffOperation na místě při zachování zdrojových a cílových textů, které diff reprezentuje. Každý optimalizátor v tomto pod-jmenném prostoru implementuje toto rozhraní, takže může být volán zaměnitelně nebo skládán do pipeline.
List<DiffOperation> diffs = new List<DiffOperation>
{
new DiffOperation(Operation.Equal, "The quick "),
new DiffOperation(Operation.Delete, "brown "),
new DiffOperation(Operation.Insert, "red "),
new DiffOperation(Operation.Equal, "fox")
};
IDiffOptimizationOperation optimizer = new OperationsMerger(EditOperationsOrder.DeleteFirst);
optimizer.Execute(diffs);Sloučení sousedních operací
OperationsMerger sloučí diff do jeho kanonické minimální podoby: sloučí sousední sekvence stejného druhu operace a pro smíšený úsek delete/insert rozčlení jakýkoli společný prefix do předchozí rovnosti a jakýkoli společný suffix do následující rovnosti.
var merger = new OperationsMerger(EditOperationsOrder.DeleteFirst);
merger.Execute(diffs);Odstraňování krátkých rovností
MergingOptimizer provádí sémantický úklidový průchod: odstraní rovnosti, které nejsou větší než úpravy je obklopující, zabalí tyto krátké společné sekvence zpět do sousedního delete/insert a poté znovu sloučí výsledek do kanonické podoby.
var semanticOptimizer = new MergingOptimizer(EditOperationsOrder.InsertFirst);
semanticOptimizer.Execute(diffs);Posouvání úprav přes rovnosti
OperationsSlideMerger posune jedinou úpravu, která je na obou stranách obklopena rovnostmi, do strany, čímž eliminuje jednu z těchto rovností a dále kanonizuje diff.
IDiffOptimizationOperation slideMerger = new OperationsSlideMerger();
slideMerger.Execute(diffs);Řízení pořadí delete/insert
Když je pro stejnou pozici vygenerován delete i insert, enum EditOperationsOrder určuje, který z nich optimalizér umístí jako první ve výsledné sekvenci operací: DeleteFirst nebo InsertFirst.
var order = EditOperationsOrder.DeleteFirst;
var optimizer = new MergingOptimizer(order);
optimizer.Execute(diffs);Tipy a osvědčené postupy
- Spusťte
OperationsMergernejprve, aby se sloučily surové úpravy před aplikací sémantických průchodů —MergingOptimizeriOperationsSlideMergerpředpokládají, že sousední operace stejného druhu již byly sloučeny. - Zvolte jednu hodnotu
EditOperationsOrdera používejte ji důsledně ve všech optimalizérech v pipeline; mícháníDeleteFirstaInsertFirstmezi průchody může zrušit pořadí, které stanovil předchozí průchod. - Všichni tři optimalizátory mění
List<DiffOperation>přímo na místě — pokud potřebujete zachovat neoptimalizovaný diff pro porovnání, nejprve klonujte seznam. - Protože každý optimalizátor implementuje
IDiffOptimizationOperation, můžete uchovávat pipeline jakoIDiffOptimizationOperation[]a volatExecutena každém v cyklu místo toho, abyste pevně kódovali každý průchod podle jména. - Aplikujte
OperationsSlideMergerpo průchodech slučování — posouvání úpravy má smysl až poté, co jsou sousední bloky stejného typu již sloučeny.
Časté problémy
| Problém | Příčina | Oprava |
|---|---|---|
| Diff stále obsahuje malé fragmentované rovnosti | Byl spuštěn jen OperationsMerger; krátké rovnosti mezi úpravami nikdy nebyly složeny | Také spusťte MergingOptimizer po OperationsMerger |
| Pořadí mazání/vkládání se neočekávaně obrací mezi průchody | Různé hodnoty EditOperationsOrder byly předány různým optimalizátorům | Použijte stejnou hodnotu EditOperationsOrder pro každý optimalizátor v pipeline |
| Zdá se, že optimalizátor nemá žádný účinek | Seznam diff byl již v kanonické podobě, nebo byl optimalizován kopií seznamu místo původní reference | Potvrďte, že předáváte stejný odkaz List<DiffOperation>, který čte downstream kód |
FAQ
Co znamená „kanonická forma“ pro diff?
To znamená, že sousední operace stejného typu byly sloučeny a jakýkoli společný prefix/suffix ve smíšených blocích mazání/vkládání byl přeneseno do sousední rovnosti, takže sekvence nemá žádnou nadbytečnou fragmentaci.
Musím použít všechny tři optimalizátory?
Ne. IDiffOptimizationOperation vám umožňuje použít jen ty průchody, které potřebujete, ale spuštění OperationsMerger před sémantickými průchody (MergingOptimizer, OperationsSlideMerger) dává nejkonzistentnější výsledky.
Jaký je rozdíl mezi OperationsMerger a MergingOptimizer?
OperationsMerger provádí strukturální slučování (běhy stejného druhu, společná předpona/přípona). MergingOptimizer jde dál a složí krátké rovnosti obklopené úpravami zpět do sousedního mazání/vložení před opětovným sloučením.
Mění EditOperationsOrder to, co diff představuje?
Ne. Pouze řídí pořadí generování mazání a vložení, které se vztahují ke stejnému místu — výsledná rekonstrukce textu není ovlivněna.
API Reference Shrnutí
| Třída / Metoda | Popis: |
|---|---|
IDiffOptimizationOperation | Rozhraní pro post-processingový průchod, který normalizuje diff přímo na místě |
IDiffOptimizationOperation.Execute(diffs) | Spouští optimalizační průchod přes mutovatelný seznam hodnot DiffOperation |
OperationsMerger | Slučuje sousední operace stejného typu a faktorizuje společnou předponu/příponu do rovností |
MergingOptimizer | Odstraňuje krátké rovnosti obklopené úpravami, poté je znovu sloučí do kanonické formy |
OperationsSlideMerger | Posouvá úpravu obklopenou rovnostmi tak, aby se jedna z nich eliminovala |
EditOperationsOrder | Výčet, který řídí, zda je na sdílené pozici emitován DeleteFirst nebo InsertFirst |