differ

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2023 License: Apache-2.0 Imports: 5 Imported by: 0

README

differ

Differ is a Go library for finding the differences between two sequences.

License

Apache-2.0


Documentation

Overview

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

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

Thanks to generics Differ 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 Differ value and NewKeyFn for how to create a DifferKeyFn 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
	Items []T
}

type BlockKeyFn added in v1.1.0

type BlockKeyFn[T any] struct {
	Tag   Tag
	Items []T
}

type Differ

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

func New

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

New returns a Differ 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 Differ, call [Blocks] (or [Spans]) to see the differences.

func (*Differ[T]) Blocks

func (me *Differ[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 items. This is the easiest method for seeing the differences in two sequences. See also [Spans].

Example (Common)
a := strings.Fields("foo\nbar\nbaz\nquux")
b := strings.Fields("foo\nbaz\nbar\nquux")
differ := New(a, b)
blocks := differ.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}
differ := New(a, b)
blocks := differ.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")
differ := New(a, b)
blocks := differ.Blocks()
for _, block := range blocks {
	fmt.Println(block.Tag, strings.Join(block.Items, " "))
}
Output:

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

func (*Differ[T]) Spans

func (me *Differ[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 DifferKeyFn added in v1.1.0

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

func NewKeyFn added in v1.1.0

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

NewKeyFn returns a DifferKeyFn 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 DifferKeyFn, call [Blocks] (or [Spans]) to see the differences.

func (*DifferKeyFn[T]) Blocks added in v1.1.0

func (me *DifferKeyFn[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 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)
	}
*/
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")}
differ := NewKeyFn(a, b, func(p Place) string { return p.name })
blocks := differ.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")}
differ := NewKeyFn(a, b,
	func(p Place) string { return strconv.Itoa(p.x) })
blocks := differ.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 (*DifferKeyFn[T]) Spans added in v1.1.0

func (me *DifferKeyFn[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 added in v1.1.0

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