Skip to content

Instantly share code, notes, and snippets.

@JeffreyZhao
Created January 27, 2010 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JeffreyZhao/287857 to your computer and use it in GitHub Desktop.
Save JeffreyZhao/287857 to your computer and use it in GitHub Desktop.
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;
}
}
}
}
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