Created
January 27, 2010 14:15
-
-
Save JeffreyZhao/287857 to your computer and use it in GitHub Desktop.
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
namespace SimpleConsole | |
{ | |
using System; | |
using System.Collections.Generic; | |
public class ArraySorter<TElement> | |
{ | |
private OrderCriteria<TElement> m_headCriteria; | |
private OrderCriteria<TElement> m_tailCriteria; | |
public ArraySorter<TElement> OrderBy<TKey>(Func<TElement, TKey> keySelector) | |
{ | |
return this.OrderBy(keySelector, null, false); | |
} | |
public ArraySorter<TElement> OrderBy<TKey>( | |
Func<TElement, TKey> keySelector, IComparer<TKey> keyComparer, bool descending) | |
{ | |
var newCriteria = new OrderCriteria<TElement, TKey>( | |
keySelector, keyComparer, descending); | |
if (this.m_headCriteria == null) | |
{ | |
this.m_headCriteria = this.m_tailCriteria = newCriteria; | |
} | |
else | |
{ | |
this.m_tailCriteria.NextCriteria = newCriteria; | |
this.m_tailCriteria = newCriteria; | |
} | |
return this; | |
} | |
public void Sort(TElement[] array) | |
{ | |
if (this.m_headCriteria == null) return; | |
var indexComparer = this.m_headCriteria.CreateComparer(array); | |
var indexArray = new int[array.Length]; | |
for (int i = 0; i < array.Length; i++) indexArray[i] = i; | |
//Array.Sort(indexArray, array, indexComparer); | |
Array.Sort(indexArray, indexComparer); | |
var arrayCopy = new TElement[array.Length]; | |
Array.Copy(array, arrayCopy, array.Length); | |
for (int i = 0; i < array.Length; i++) | |
{ | |
array[i] = arrayCopy[indexArray[i]]; | |
} | |
} | |
} | |
internal abstract class OrderCriteria<TElement> | |
{ | |
public abstract IComparer<int> CreateComparer(TElement[] array); | |
public OrderCriteria<TElement> NextCriteria; | |
} | |
internal class OrderCriteria<TElement, TKey> : OrderCriteria<TElement> | |
{ | |
private IComparer<TKey> m_keyComparer; | |
private Func<TElement, TKey> m_keySelector; | |
private bool m_descending; | |
public OrderCriteria( | |
Func<TElement, TKey> keySelector, IComparer<TKey> keyComparer, bool decesnding) | |
{ | |
this.m_keySelector = keySelector; | |
this.m_keyComparer = keyComparer; | |
this.m_descending = decesnding; | |
} | |
public override IComparer<int> CreateComparer(TElement[] array) | |
{ | |
var keyArray = new TKey[array.Length]; | |
for (int i = 0; i < array.Length; i++) | |
{ | |
keyArray[i] = this.m_keySelector(array[i]); | |
} | |
var comparer = new IndexComparer<TKey>(keyArray, this.m_keyComparer, this.m_descending); | |
if (this.NextCriteria != null) | |
{ | |
comparer.NextIndexComparer = this.NextCriteria.CreateComparer(array); | |
} | |
return comparer; | |
} | |
} | |
internal class IndexComparer<TKey> : IComparer<int> | |
{ | |
public IComparer<int> NextIndexComparer; | |
private TKey[] m_keyArray; | |
private IComparer<TKey> m_keyComparer; | |
private bool m_decesnding; | |
public IndexComparer(TKey[] keyArray, IComparer<TKey> keyComparer, bool decesnding) | |
{ | |
this.m_keyArray = keyArray; | |
this.m_keyComparer = keyComparer ?? Comparer<TKey>.Default; | |
this.m_decesnding = decesnding; | |
} | |
public int Compare(int indexX, int indexY) | |
{ | |
var keyX = this.m_keyArray[indexX]; | |
var keyY = this.m_keyArray[indexY]; | |
var result = this.m_keyComparer.Compare(keyX, keyY); | |
if (result == 0) | |
{ | |
return this.NextIndexComparer == null ? 0 : | |
this.NextIndexComparer.Compare(indexX, indexY); | |
} | |
else | |
{ | |
return this.m_decesnding ? -result : result; | |
} | |
} | |
} | |
} |
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
namespace SimpleConsole | |
{ | |
using System; | |
using System.Linq; | |
public class Person | |
{ | |
public int ID; | |
} | |
class Program | |
{ | |
/// <summary> | |
/// The main entry point for the application. | |
/// </summary> | |
static void Main(string[] args) | |
{ | |
CodeTimer.Initialize(); | |
var random = new Random(DateTime.Now.Millisecond); | |
var array = Enumerable.Repeat(0, 1000 * 500).Select(_ => new Person { ID = random.Next() }).ToArray(); | |
CodeTimer.Time("SortWithLinq", 10, | |
() => SortWithLinq(CloneArray(array))); | |
CodeTimer.Time("SortWithArraySorter", 10, | |
() => SortWithArraySorter(CloneArray(array))); | |
Console.ReadLine(); | |
} | |
static void SortWithLinq(Person[] people) | |
{ | |
var sorted = | |
(from i in people | |
orderby i.ID | |
select i).ToList(); | |
} | |
static void SortWithArraySorter(Person[] people) | |
{ | |
new ArraySorter<Person>().OrderBy(p => p.ID).Sort(people); | |
} | |
static T[] CloneArray<T>(T[] source) | |
{ | |
var dest = new T[source.Length]; | |
Array.Copy(source, dest, source.Length); | |
return dest; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment