diff2

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 27, 2023 License: Apache-2.0 Imports: 6 Imported by: 0

README

diff2

Diff2 a Go package for finding the differences between two sequences.

(This package is based on and supercedes my go-diff/differ package.)

License

Apache-2.0


Documentation

Overview

Diff2 is a package for finding the differences between two sequences.

Diff2 uses a sequence matcher based on a slightly simplified version of Python's difflib sequence matcher.

Thanks to generics Diff2 can compare any two slices of comparables. (Although comparing float sequences is not recommended.) And using a key function it can also compare two slices of structs.

See New for how to create a Diff value and NewKeyFn for how to create a DiffKeyFn value which can be used to compare sequences of structs.

Index

Examples

Constants

This section is empty.

Variables

View Source
var Version string

Functions

This section is empty.

Types

type Block

type Block[T comparable] struct {
	Tag    Tag
	Aitems []T
	Bitems []T
}

func (*Block[T]) Items

func (me *Block[T]) Items() []T

type BlockKeyFn

type BlockKeyFn[T any] struct {
	Tag    Tag
	Aitems []T
	Bitems []T
}

func (*BlockKeyFn[T]) Items

func (me *BlockKeyFn[T]) Items() []T

type Diff

type Diff[T comparable] struct {
	A []T
	B []T
	// contains filtered or unexported fields
}

func New

func New[T comparable](a, b []T) *Diff[T]

New returns a Diff value based on the provided a and b slices. These slices are only ever read and may be accessed as .A and .B. After creating a Diff, call [Blocks] (or [Spans]) to see the differences.

func (*Diff[T]) Blocks

func (me *Diff[T]) Blocks() []Block[T]

Blocks returns a sequence of Block values representing how to go from a to b. Each block has a Tag and a sequence of A's and B's items. This is the easiest method for seeing the differences in two sequences. See also [Spans].

Example (Changesnoreplace)
a := strings.Fields("the quick brown fox jumped over the lazy dogs")
b := strings.Fields("a quick red fox jumped over some lazy hogs")
diff := New(a, b)
blocks := diff.Blocks()
for _, block := range blocks {
	if block.Tag != Equal {
		if block.Tag == Replace {
			fmt.Println(Delete, strings.Join(block.Aitems, ""))
			fmt.Println(Insert, strings.Join(block.Bitems, ""))
		} else {
			fmt.Println(block.Tag, strings.Join(block.Items(), " "))
		}
	}
}
Output:

- the
+ a
- brown
+ red
- the
+ some
- dogs
+ hogs
Example (Changesonly)
a := strings.Fields("the quick brown fox jumped over the lazy dogs")
b := strings.Fields("a quick red fox jumped over some lazy hogs")
diff := New(a, b)
blocks := diff.Blocks()
for _, block := range blocks {
	if block.Tag != Equal {
		fmt.Println(block.Tag, strings.Join(block.Items(), " "))
	}
}
Output:

% a
% red
% some
% hogs
Example (Common)
a := strings.Fields("foo\nbar\nbaz\nquux")
b := strings.Fields("foo\nbaz\nbar\nquux")
diff := New(a, b)
blocks := diff.Blocks()
for _, block := range blocks {
	fmt.Println(block.Tag, strings.Join(block.Items(), " "))
}
Output:

= foo
+ baz
= bar
- baz
= quux
Example (Ints)
a := []int{1, 2, 3, 4, 5, 6}
b := []int{2, 3, 5, 7}
diff := New(a, b)
blocks := diff.Blocks()
for _, block := range blocks {
	fmt.Println(block.Tag, gong.StringForSlice(block.Items()))
}
Output:

- 1
= 2 3
- 4
= 5
% 7
Example (Strings)
a := strings.Fields("the quick brown fox jumped over the lazy dogs")
b := strings.Fields("a quick red fox jumped over some lazy hogs")
diff := New(a, b)
blocks := diff.Blocks()
for _, block := range blocks {
	fmt.Println(block.Tag, strings.Join(block.Items(), " "))
}
Output:

% a
= quick
% red
= fox jumped over
% some
= lazy
% hogs

func (*Diff[T]) Spans

func (me *Diff[T]) Spans() []Span

Spans returns a sequence of Span values representing how to go from a to b. Each span has a Tag and a sequence of [Quad]s. Each Quad holds a pair of start/end indexes into a and b. The easiest method for seeing the differences in two sequences is [Blocks].

type DiffKeyFn

type DiffKeyFn[T any] struct {
	A []T
	B []T
	// contains filtered or unexported fields
}

func NewKeyFn

func NewKeyFn[T any](a, b []T, keyfn KeyFn[T]) *DiffKeyFn[T]

NewKeyFn returns a DiffKeyFn value based on the provided a and b slices. These slices are only ever read and may be accessed as .A and .B. After creating a DiffKeyFn, call [Blocks] (or [Spans]) to see the differences.

func (*DiffKeyFn[T]) Blocks

func (me *DiffKeyFn[T]) Blocks() []BlockKeyFn[T]

Blocks returns a sequence of BlockKeyFn values representing how to go from a to b. Each block has a Tag and a sequence of A's and B's items. This is the easiest method for seeing the differences in two sequences. See also [Spans].

Example (Namekey)
/*
	type Place struct {
	x    int
	y    int
	name string
	}

	func newPlace(x, y int, name string) Place {
	return Place{x: x, y: y, name: name}
	}

	func (me *Place) String() string {
	return fmt.Sprintf("Place{%d,%d,%q}", me.x, me.y, me.name)
	}
*/ame)
	}
*/
a := []Place{newPlace(1, 2, "foo"), newPlace(3, 4, "bar"),
	newPlace(5, 6, "baz"), newPlace(7, 8, "quux")}
b := []Place{newPlace(1, 2, "foo"), newPlace(6, 2, "baz"),
	newPlace(3, 4, "bar"), newPlace(7, 8, "quux")}
diff := NewKeyFn(a, b, func(p Place) string { return p.name })
blocks := diff.Blocks()
for _, block := range blocks {
	for _, item := range block.Items() {
		fmt.Println(block.Tag, item.String())
	}
}
Output:

= Place{1,2,"foo"}
+ Place{6,2,"baz"}
= Place{3,4,"bar"}
- Place{5,6,"baz"}
= Place{7,8,"quux"}
Example (Xkey)
// a: [1 3 5 7]
// b: [1 6 3 7]
a := []Place{newPlace(1, 2, "foo"), newPlace(3, 4, "bar"),
	newPlace(5, 6, "baz"), newPlace(7, 8, "quux")}
b := []Place{newPlace(1, 2, "foo"), newPlace(6, 2, "bar"),
	newPlace(3, 4, "baz"), newPlace(7, 8, "quux")}
diff := NewKeyFn(a, b,
	func(p Place) string { return strconv.Itoa(p.x) })
blocks := diff.Blocks()
for _, block := range blocks {
	for _, item := range block.Items() {
		fmt.Println(block.Tag, item.String())
	}
}
Output:

= Place{1,2,"foo"}
+ Place{6,2,"bar"}
= Place{3,4,"baz"}
- Place{5,6,"baz"}
= Place{7,8,"quux"}

func (*DiffKeyFn[T]) Spans

func (me *DiffKeyFn[T]) Spans() []Span

Spans returns a sequence of Span values representing how to go from a to b. Each span has a Tag and a sequence of [Quad]s. Each Quad holds a pair of start/end indexes into a and b. The easiest method for seeing the differences in two sequences is [Blocks].

type KeyFn

type KeyFn[T any] func(x T) string

type Quad

type Quad struct {
	Astart int
	Aend   int
	Bstart int
	Bend   int
}

type Span

type Span struct {
	Tag Tag
	Quad
}

func (Span) String

func (me Span) String() string

type Tag

type Tag uint8
const (
	Equal Tag = iota
	Insert
	Delete
	Replace
)

func (Tag) String

func (me Tag) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL