Last active
December 2, 2016 13:06
-
-
Save keith-kurak/7a57ba863e8c05a3753a52dfeeaf097e to your computer and use it in GitHub Desktop.
Simple match Big-O comparison
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SomeContainerOfThings | |
{ | |
List<IThing> Things {get;set;} | |
//old - performed at O(N^2) | |
IEnumerable<IThing> GetThingsAlsoIn(SomeContainerOfThings other) | |
{ | |
return this.Things.Where(thisThing => other.Things.Any(otherThing => thisThing.Name == otherThing.Name)); | |
} | |
//new - performed at 2 O(N) | |
IEnumerable<IThing> GetThingsAlsoIn(SomeContainerOfThings other) | |
{ | |
var indexedThings = this.Things.ToDictionary(thing => thing.Name); | |
return other.Things.Where(otherThing => indexedThings.ContainsKey(otherThing.Name); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[TestClass] | |
public class SomeContainerOfThingsTests | |
{ | |
private SomeContainerOfThings GetFakeContainerForRange(int nameStart, int nameEnd) | |
{ | |
//... (this gets a container containing one IThing for each number between the start and the end) | |
} | |
private class CountingThing: IThing | |
{ | |
public TimesAccessed {get;set;} | |
private string name; | |
public Name | |
{ | |
get | |
{ | |
this.TimesAccessed++; | |
return this.name; | |
} | |
set | |
{ | |
this.Name = value; | |
} | |
} | |
} | |
//sums together TimesAccessed of each CounterThing in the two containers | |
private int GetTotalTimesAccessed(SomeContainerOfThings container1, SomeContainerOfThings container2) | |
{ | |
return container1.Things.Sum(t => (t as CounterThing).TimesAccessed) + container2.Things.Sum(t => (t as CounterThing).TimesAccessed) | |
} | |
[TestMethod] | |
public void GetThingsAlsoIn_PerformsAtBigOofNLevel() | |
{ | |
//arrange | |
var container1 = GetFakeContainerForRange(1, 1000); //worst case = best case. This algorithm takes 2 O(n) regardless | |
var container2 = GetFakeContainerForRange(1, 1000); | |
//act | |
container1.GetThingsAlsoIn(container2).ToList(); //force enumeration | |
//assert | |
var timesAccessed = GetTotalTimesAccessed(container1, container2); | |
Assert.IsTrue(timesAccessed <= 2000); | |
} | |
//old algorithm extracted to show how bad it performs | |
[TestMethod] | |
public void GetThingsAlsoIn_OldAlgorithm_PerformsAtBigOofNSquaredLevel() | |
{ | |
//arrange | |
var container1 = GetFakeContainerForRange(1, 1000); //worst case for this algorithm = no matches | |
var container2 = GetFakeContainerForRange(1001, 2000); | |
//act | |
//copy algorithm right in since its no longer in current version | |
container1.Things.Where(thisThing => container2.Things.Any(otherThing => thisThing.Name == otherThing.Name)).ToList(); | |
//assert | |
var timesAccessed = GetTotalTimesAccessed(container1, container2); | |
Assert.IsTrue(timesAccessed == 1000000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment