- 你所在位置:首页 〉VS.net〉C#〉C#高级编程(4版)〉反转Sorted List里的内容
- 反转Sorted List里的内容
- 作者:abatei 文章来源:博客园 发布日期:2008-02-21 浏览次数:209
-
- 打印这篇文章
-
问题
您希望在数组和列表类型中可以反转sorted list里的内容同时又维持SortedList和SortedList< T>类原来的功能。无论是SortedList还是泛型SortedList< T>类都直接提供了完成这个功能的方法而又不需要重填列表。
解决方案
ReversibleSortedList< TKey, TValue>类提供了这些功能,它基于SortedList< TKey, TValue>类,所以拥有相同的功能,它提供了额外的功能是很容易反转已排序的列表。
在实例化ReversibleSortedList< TKey, TValue>之后,键是整数类型,值是字符串类型,一连串无序的数字和它们的文本表达被插入到列表中。这些项目是这样显示的:
ReversibleSortedList< int, string> rsl = new ReversibleSortedList< int, string>();
rsl.Add(2, "2");
rsl.Add(5, "5");
rsl.Add(3, "3");
rsl.Add(1, "1");
foreach (KeyValuePair< int, string> kvp in rsl)


{
Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);
}

列表输出显示为按升序排序(默认):
1 12 23 35 5现在排列顺序通过设置ReversibleSortedList的SortDirection属性被反转为降序。为了重新排序需要调用Sort()方法。结果如下:
// 转换排序方向.
rsl.Comparer.SortDirection = ListSortDirection.Descending;
// 重排列表.
rsl.Sort();
foreach (KeyValuePair< int, string> kvp in rsl)


{
Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);
}

这一次,输出为降序:
5 5
3 32 21 1
当把一个新项添加进列表,它将按当前的排列顺序被添加进去,但在添加完所有项后马上进行反转,就可以保持列表中元素的顺序。
rsl.Add(4, "4");
foreach (KeyValuePair< int, string> kvp in rsl)

{
Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);
}
// 转换排序方向.
rsl.Comparer.SortDirection = ListSortDirection.Ascending;
// 重排列表.
rsl.Sort();
foreach (KeyValuePair< int, string> kvp in rsl)

{
Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);
}

可以看到新项即按降序也按升序排列:
5 54 43 32 21 11 12 23 34 45 5ReversibleSortedList< TKey, TValue>包含一个实现了IComparer< T>接口的嵌套类SortDirectionComparer< T>。这个类可以在“讨论”这一节中的ReversibleSortedList< TKey, TValue>代码中看到。一个实现了IComparer< T>接口的类可以做为ReversibleSortedList< TKey, TValue>构造方法的参数来改变默认的排序。IComparer< T>接口实现了Compare方法:
class Program

{
public int Compare(T lhs, T rhs)

{
int compareResult =
lhs.ToString().CompareTo(rhs.ToString());
// 如果为降序, 则反转
if (SortDirection == ListSortDirection.Descending)
compareResult *= -1;
return compareResult;
}
}

Compare方法使用了SortDirectionComparer< T>类的SortDirection属性来决定项的排序。这个属性在ReversibleSortedList< TKey, TValue>的内部类SortDirectionComparer< T>实例中被设置。SortDirection属性是在构造方法中被设置的,代码如下:
public ReversibleSortedList()

{
this.keys = ReversibleSortedList< TKey, TValue>.emptyKeys;
this.values = ReversibleSortedList< TKey, TValue>.emptyValues;
this._size = 0;
this._sortDirectionComparer = new SortDirectionComparer< TKey>();
this._currentSortDirection = this._sortDirectionComparer.SortDirection;
}

这允许它在指定时间内反转排列顺序,但并没有重排列表中已存在的项。为了实现这个功能,需要在Reversible-SortedList< TKey, TValue>类中添加一个新的Sort()方法以重排列表。代码如下:
public void Sort()


{
//检查是否跟现有排序方向相同.
if (this._currentSortDirection != this._sortDirectionComparer.SortDirection)

{
// 如果不同,则进行反转.
Array.Reverse(this.keys, 0, this._size);
Array.Reverse(this.values, 0, this._size);
// 设置当前排序.
this._currentSortDirection = this._sortDirectionComparer.SortDirection;
}
}

讨论
例4-3是ReversibleSortedList< TKey, TValue>类的所有代码:
(译者注:这个类的代码很恐怖,接近1300行,不过代码很规范,感觉应该是商业代码,非常值得借鉴。将来有时间我会专门写文章分析它。请关注:我的博客:http://cgbluesky.blog.163.com/)
例4-3 ReversibleSortedList类
[Serializable, ComVisible(false), DebuggerDisplay("Count = {Count}")]
public class ReversibleSortedList< TKey, TValue> :
IDictionary< TKey, TValue>, ICollection< KeyValuePair< TKey, TValue>>,
IEnumerable< KeyValuePair< TKey, TValue>>,
IDictionary, ICollection, IEnumerable


{

SortDirectionComparer类定义#region SortDirectionComparer类定义
public class SortDirectionComparer< T> : IComparer< T>

{ //ListSortDirection 枚举,有两个值:
//Ascending按升序排列,Descending按降序排列
private System.ComponentModel.ListSortDirection _sortDir;
//构造方法
public SortDirectionComparer()

{ //默认为升序
_sortDir = ListSortDirection.Ascending;
}
//重载构造方法
public SortDirectionComparer(ListSortDirection sortDir)

{
_sortDir = sortDir;
}
//排序方向属性
public System.ComponentModel.ListSortDirection SortDirection

{

get
{ return _sortDir; }

set
{ _sortDir = value; }
}
//实现IComparer< T>接口的方法
public int Compare(T lhs, T rhs)

{
int compareResult =
lhs.ToString().CompareTo(rhs.ToString());

// If order is DESC, reverse this comparison.
if (SortDirection == ListSortDirection.Descending)
compareResult *= -1;
return compareResult;
}
}
#endregion // SortDirectionComparer


构造方法#region 构造方法
//类型构造器
static ReversibleSortedList()

{
ReversibleSortedList< TKey, TValue>.emptyKeys = new TKey[0];
ReversibleSortedList< TKey, TValue>.emptyValues = new TValue[0];
}
//无参构造方法
public ReversibleSortedList()

{
this.keys = ReversibleSortedList< TKey, TValue>.emptyKeys;
this.values = ReversibleSortedList< TKey, TValue>.emptyValues;
this._size = 0;
this._sortDirectionComparer = new SortDirectionComparer< TKey>();
this._currentSortDirection = this._sortDirectionComparer.SortDirection;
}
//用于指定排序方向的构造方法
public ReversibleSortedList(SortDirectionComparer< TKey> comparer)
: this()

{
if (comparer != null)

{
this._sortDirectionComparer = comparer;
this._currentSortDirection = _sortDirectionComparer.SortDirection;
}
}
//用于指定字典的构造方法
public ReversibleSortedList(IDictionary< TKey, TValue> dictionary)
: this(dictionary, (SortDirectionComparer< TKey>)null)

{
}
//用于指定列表容量的构造方法
public ReversibleSortedList(int capacity)

{
if (capacity < 0)

{
throw new ArgumentOutOfRangeException(
"capacity", "Non-negative number required");
}
this.keys = new TKey[capacity];
this.values = new TValue[capacity];
this._sortDirectionComparer = new SortDirectionComparer< TKey>();
this._currentSortDirection = _sortDirectionComparer.SortDirection;
}
//用于指定字典和排序方向的构造方法
public ReversibleSortedList(IDictionary< TKey, TValue> dictionary,
SortDirectionComparer< TKey> comparer)
: this((dictionary != null) ? dictionary.Count : 0, comparer)

{
if (dictionary == null)

{
throw new ArgumentNullException("dictionary");
}
dictionary.Keys.CopyTo(this.keys, 0);
dictionary.Values.CopyTo(this.values, 0);
Array.Sort< TKey, TValue>(this.keys, this.values,
this._sortDirectionComparer);
this._size = dictionary.Count;
}
//用于指定容量和排序方向的构造方法
public ReversibleSortedList(int capacity, SortDirectionComparer< TKey> comparer)
: this(comparer)

{
this.Capacity = capacity;
}
