Skip to content

Commit 2e07510

Browse files
authored
introduced different result orders, prepared release 1.1.0 (#4)
* introduced different result orders * prepared release 1.1.0
1 parent 2a3e865 commit 2e07510

7 files changed

Lines changed: 664 additions & 43 deletions

File tree

README.md

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,14 @@ B: c b a b a c
1111

1212
To do this, we use the following code:
1313
```csharp
14+
// using spkl.Diffs;
1415
string[] a = new[] { "a", "b", "c", "a", "b", "b", "a" };
1516
string[] b = new[] { "c", "b", "a", "b", "a", "c" };
1617
MyersDiff<string> diff = new MyersDiff<string>(a, b);
1718
```
1819
Using generic typing, you can diff all sorts of types. You can also customize which values are considered equal by specifying a third constructor parameter (IEqualityComparer&lt;T&gt;).
1920

20-
There are two methods to access the results: `GetResult()` and `GetEditScript()`.
21-
22-
### GetResult()
23-
`GetResult()` returns the resulting diff as a sequence of tuples that represent lines. In this case, the return value would look like this:
24-
| ResultType | AItem | BItem |
25-
|------------|-------|-------|
26-
| A | a | |
27-
| B | | c |
28-
| Both | b | b |
29-
| A | c | |
30-
| Both | a | a |
31-
| Both | b | b |
32-
| A | b | |
33-
| Both | a | a |
34-
| B | | c |
35-
36-
This is similar to how the result would be displayed in a visual comparison application. The AItem and BItem columns contain sequence A and B, respectively. The ResultType column shows whether a line contains a value from sequence A, B, or from both. You can see which values were matched with each other.
21+
There are two methods to access the results: `GetEditScript()` and `GetResult()`.
3722

3823
### GetEditScript()
3924
`GetEditScript()` returns a sequence of edit instructions. You can understand these as instructions to follow to transform sequence A to sequence B. Every instruction contains four integers, a starting line number in A and B and the number of lines to add or remove. In this case, the return value would look like this:
@@ -65,3 +50,36 @@ To better understand this, let's follow these instructions:
6550
*(This adds the last "c")*
6651

6752
Following these instructions, `abcabba` is transformed to `cbabac`.
53+
54+
55+
### GetResult()
56+
`GetResult()` returns the resulting diff as a sequence of tuples that represent lines. In this case, the return value would look like this:
57+
| ResultType | AItem | BItem |
58+
|------------|-------|-------|
59+
| A | a | |
60+
| B | | c |
61+
| Both | b | b |
62+
| A | c | |
63+
| Both | a | a |
64+
| Both | b | b |
65+
| A | b | |
66+
| Both | a | a |
67+
| B | | c |
68+
69+
This is similar to how the result would be displayed in a visual comparison application. The AItem and BItem columns contain sequence A and B, respectively. The ResultType column shows whether a line contains a value from sequence A, B, or from both. You can see which values were matched with each other.
70+
71+
### GetResult(ResultOrder)
72+
You can specify the order in which you want unmatched lines to appear by using the `GetResult(ResultOrder)` overload. To visualize this, we need to use a new example.
73+
```
74+
A: a b c
75+
B: x y
76+
```
77+
78+
The following table shows how the result would be returned when specifying the different ResultOrder values AABB, BBAA, ABAB and BABA:
79+
| AABB | BBAA | ABAB | BABA |
80+
|:----:|:----:|:----:|:----:|
81+
| a - | - x | a - | - x |
82+
| b - | - y | - x | a - |
83+
| c - | a - | b - | - y |
84+
| - x | b - | - y | b - |
85+
| - y | c - | c - | c - |

src/Diffs.csproj

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
<Copyright>Copyright (c) 2021 Sebastian Fischer</Copyright>
1212
<RepositoryUrl>https://github.com/spkl/Diffs</RepositoryUrl>
1313
<AssemblyVersion>1.0.0.0</AssemblyVersion>
14-
<FileVersion>1.0.1.0</FileVersion>
15-
<Version>1.0.1</Version>
14+
<FileVersion>1.1.0.0</FileVersion>
15+
<Version>1.1.0</Version>
1616
<SignAssembly>true</SignAssembly>
1717
<AssemblyOriginatorKeyFile>..\keys\spkl.Diffs.snk</AssemblyOriginatorKeyFile>
1818
<DelaySign>false</DelaySign>
@@ -22,8 +22,7 @@
2222
This project uses Semantic Versioning (https://semver.org/).</Description>
2323
<PackageTags>diff diffs difference algorithm ses shortest edit script myers</PackageTags>
2424
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
25-
<PackageReleaseNotes>- Added documentation comments to all public types and methods to explain usage.
26-
- Fixed issue where the comparer passed into the MyersDiff&lt;T&gt; constructor was ignored.</PackageReleaseNotes>
25+
<PackageReleaseNotes>- Introduced new GetResult overload to customize the preferred order of unmatched lines.</PackageReleaseNotes>
2726
</PropertyGroup>
2827

2928
<ItemGroup>

src/MyersDiff.cs renamed to src/MyersDiff{T}.cs

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,43 @@ private bool AreEqual(int aIndex, int bIndex)
8686
/// BItem: The item from sequence B, this is the default value/null if resultType is <see cref="ResultType.A"/>.
8787
/// </summary>
8888
/// <returns>An enumerable of diff lines containing one unmatched or two matched items.</returns>
89+
/// <remarks>This is this equal to calling <see cref="GetResult(ResultOrder)"/> with <see cref="ResultOrder.AABB"/>.</remarks>
8990
public IEnumerable<(ResultType ResultType, T AItem, T BItem)> GetResult()
9091
{
92+
return this.GetResult(ResultOrder.AABB);
93+
}
94+
95+
/// <summary>
96+
/// Gets the calculated diff result in the form of matched items/lines:
97+
/// ResultType: Specifies whether the line includes only an item from A, from B or from both sequences.
98+
/// AItem: The item from sequence A; this is the default value/null if resultType is <see cref="ResultType.B"/>.
99+
/// BItem: The item from sequence B, this is the default value/null if resultType is <see cref="ResultType.A"/>.
100+
/// </summary>
101+
/// <param name="order">The order in which unmatched items/lines are returned.</param>
102+
/// <returns>An enumerable of diff lines containing one unmatched or two matched items.</returns>
103+
public IEnumerable<(ResultType ResultType, T AItem, T BItem)> GetResult(ResultOrder order)
104+
{
105+
ResultType GetPreferredNext(ResultType current)
106+
{
107+
if (current == ResultType.Both)
108+
{
109+
// A first or B first
110+
return (order == ResultOrder.ABAB || order == ResultOrder.AABB) ? ResultType.A : ResultType.B;
111+
}
112+
113+
if (order == ResultOrder.AABB || order == ResultOrder.BBAA)
114+
{
115+
// Section mode - keep same side.
116+
return current;
117+
}
118+
else
119+
{
120+
// Line mode - switch side.
121+
return current == ResultType.A ? ResultType.B : ResultType.A;
122+
}
123+
}
124+
125+
ResultType preferredNext = GetPreferredNext(ResultType.Both);
91126
int currentA = 0, currentB = 0;
92127
while (currentA < this.aRemoved.Length || currentB < this.bAdded.Length)
93128
{
@@ -98,16 +133,37 @@ private bool AreEqual(int aIndex, int bIndex)
98133
yield return (ResultType.Both, this.aValues[currentA], this.bValues[currentB]);
99134
currentA++;
100135
currentB++;
136+
preferredNext = GetPreferredNext(ResultType.Both);
101137
}
102-
else if (this.aRemoved[currentA])
138+
else if (preferredNext == ResultType.A)
103139
{
104-
yield return (ResultType.A, this.aValues[currentA], default(T));
105-
currentA++;
140+
if (this.aRemoved[currentA])
141+
{
142+
yield return (ResultType.A, this.aValues[currentA], default(T));
143+
currentA++;
144+
preferredNext = GetPreferredNext(ResultType.A);
145+
}
146+
else if (this.bAdded[currentB])
147+
{
148+
yield return (ResultType.B, default(T), this.bValues[currentB]);
149+
currentB++;
150+
preferredNext = GetPreferredNext(ResultType.B);
151+
}
106152
}
107-
else if (this.bAdded[currentB])
153+
else // preferredNext == ResultType.B
108154
{
109-
yield return (ResultType.B, default(T), this.bValues[currentB]);
110-
currentB++;
155+
if (this.bAdded[currentB])
156+
{
157+
yield return (ResultType.B, default(T), this.bValues[currentB]);
158+
currentB++;
159+
preferredNext = GetPreferredNext(ResultType.B);
160+
}
161+
else if (this.aRemoved[currentA])
162+
{
163+
yield return (ResultType.A, this.aValues[currentA], default(T));
164+
currentA++;
165+
preferredNext = GetPreferredNext(ResultType.A);
166+
}
111167
}
112168
}
113169
else if (currentA < this.aRemoved.Length)

src/ResultOrder.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace spkl.Diffs
2+
{
3+
/// <summary>
4+
/// Determines in which order the <see cref="MyersDiff{T}.GetResult(ResultOrder)"/> method returns items.
5+
/// </summary>
6+
public enum ResultOrder
7+
{
8+
/// <summary>
9+
/// Items are ordered in alternating sections, first A, then B.
10+
/// </summary>
11+
AABB,
12+
/// <summary>
13+
/// Items are ordered in alternating sections, first B, then A.
14+
/// </summary>
15+
BBAA,
16+
/// <summary>
17+
/// Items are ordered in alternating lines, first A, then B.
18+
/// </summary>
19+
ABAB,
20+
/// <summary>
21+
/// Items are ordered in alternating lines, first B, then A.
22+
/// </summary>
23+
BABA
24+
}
25+
}

test/MyersDiffClass.ReferenceCase.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ public string BString
2424
}
2525
}
2626

27-
public (ResultType ResultType, string AItem, string BItem)[] Result { get; set; }
27+
public (ResultType ResultType, string AItem, string BItem)[] ResultAABB { get; set; }
28+
29+
public (ResultType ResultType, string AItem, string BItem)[] ResultBBAA { get; set; }
30+
31+
public (ResultType ResultType, string AItem, string BItem)[] ResultABAB { get; set; }
32+
33+
public (ResultType ResultType, string AItem, string BItem)[] ResultBABA { get; set; }
2834

2935
public (int LineA, int LineB, int CountA, int CountB)[] EditScript { get; set; }
3036

@@ -34,4 +40,4 @@ public override string ToString()
3440
}
3541
}
3642
}
37-
}
43+
}

0 commit comments

Comments
 (0)